Commit e80313f9 authored by Robert Schilling's avatar Robert Schilling

Conditionally destroy a ressource

parent 998afa5f
...@@ -67,15 +67,14 @@ module API ...@@ -67,15 +67,14 @@ module API
end end
delete ":id/access_requests/:user_id" do delete ":id/access_requests/:user_id" do
source = find_source(source_type, params[:id]) source = find_source(source_type, params[:id])
member = source.public_send(:requesters).find_by!(user_id: params[:user_id]) member = source.requesters.find_by!(user_id: params[:user_id])
check_unmodified_since(member.updated_at) destroy_conditionally!(member) do
status 204
::Members::DestroyService.new(source, current_user, params) ::Members::DestroyService.new(source, current_user, params)
.execute(:requesters) .execute(:requesters)
end end
end end
end end
end end
end
end end
...@@ -85,12 +85,10 @@ module API ...@@ -85,12 +85,10 @@ module API
end end
delete "#{endpoint}/:award_id" do delete "#{endpoint}/:award_id" do
award = awardable.award_emoji.find(params[:award_id]) award = awardable.award_emoji.find(params[:award_id])
check_unmodified_since(award.updated_at)
unauthorized! unless award.user == current_user || current_user.admin? unauthorized! unless award.user == current_user || current_user.admin?
status 204 destroy_conditionally!(award)
award.destroy
end end
end end
end end
......
...@@ -122,12 +122,10 @@ module API ...@@ -122,12 +122,10 @@ module API
end end
delete "/lists/:list_id" do delete "/lists/:list_id" do
authorize!(:admin_list, user_project) authorize!(:admin_list, user_project)
list = board_lists.find(params[:list_id]) list = board_lists.find(params[:list_id])
check_unmodified_since(list.updated_at)
destroy_conditionally!(list) do |list|
service = ::Boards::Lists::DestroyService.new(user_project, current_user) service = ::Boards::Lists::DestroyService.new(user_project, current_user)
unless service.execute(list) unless service.execute(list)
render_api_error!({ error: 'List could not be deleted!' }, 400) render_api_error!({ error: 'List could not be deleted!' }, 400)
end end
...@@ -135,4 +133,5 @@ module API ...@@ -135,4 +133,5 @@ module API
end end
end end
end end
end
end end
...@@ -90,10 +90,8 @@ module API ...@@ -90,10 +90,8 @@ module API
end end
delete ':id' do delete ':id' do
message = find_message message = find_message
check_unmodified_since(message.updated_at)
status 204 destroy_conditionally!(message)
message.destroy
end end
end end
end end
......
...@@ -125,10 +125,7 @@ module API ...@@ -125,10 +125,7 @@ module API
key = user_project.deploy_keys_projects.find_by(deploy_key_id: params[:key_id]) key = user_project.deploy_keys_projects.find_by(deploy_key_id: params[:key_id])
not_found!('Deploy Key') unless key not_found!('Deploy Key') unless key
check_unmodified_since(key.updated_at) destroy_conditionally!(key)
status 204
key.destroy
end end
end end
end end
......
...@@ -78,10 +78,8 @@ module API ...@@ -78,10 +78,8 @@ module API
authorize! :update_environment, user_project authorize! :update_environment, user_project
environment = user_project.environments.find(params[:environment_id]) environment = user_project.environments.find(params[:environment_id])
check_unmodified_since(environment.updated_at)
status 204 destroy_conditionally!(environment)
environment.destroy
end end
desc 'Stops an existing environment' do desc 'Stops an existing environment' do
......
...@@ -118,11 +118,10 @@ module API ...@@ -118,11 +118,10 @@ module API
group = find_group!(params[:id]) group = find_group!(params[:id])
authorize! :admin_group, group authorize! :admin_group, group
check_unmodified_since(group.updated_at) destroy_conditionally!(group) do |group|
status 204
::Groups::DestroyService.new(group, current_user).execute ::Groups::DestroyService.new(group, current_user).execute
end end
end
desc 'Get a list of projects in this group.' do desc 'Get a list of projects in this group.' do
success Entities::Project success Entities::Project
......
...@@ -11,14 +11,25 @@ module API ...@@ -11,14 +11,25 @@ module API
declared(params, options).to_h.symbolize_keys declared(params, options).to_h.symbolize_keys
end end
def check_unmodified_since(last_modified) def check_unmodified_since!(last_modified)
if_unmodified_since = Time.parse(headers['If-Unmodified-Since']) if headers.key?('If-Unmodified-Since') rescue nil if_unmodified_since = Time.parse(headers['If-Unmodified-Since']) rescue nil
if if_unmodified_since && if_unmodified_since < last_modified if if_unmodified_since && last_modified > if_unmodified_since
render_api_error!('412 Precondition Failed', 412) render_api_error!('412 Precondition Failed', 412)
end end
end end
def destroy_conditionally!(resource, last_update_field: :updated_at)
check_unmodified_since!(resource.public_send(last_update_field))
status 204
if block_given?
yield resource
else
resource.destroy
end
end
def current_user def current_user
return @current_user if defined?(@current_user) return @current_user if defined?(@current_user)
......
...@@ -230,10 +230,8 @@ module API ...@@ -230,10 +230,8 @@ module API
not_found!('Issue') unless issue not_found!('Issue') unless issue
authorize!(:destroy_issue, issue) authorize!(:destroy_issue, issue)
check_unmodified_since(issue.updated_at)
status 204 destroy_conditionally!(issue)
issue.destroy
end end
desc 'List merge requests closing issue' do desc 'List merge requests closing issue' do
......
...@@ -56,10 +56,7 @@ module API ...@@ -56,10 +56,7 @@ module API
label = user_project.labels.find_by(title: params[:name]) label = user_project.labels.find_by(title: params[:name])
not_found!('Label') unless label not_found!('Label') unless label
check_unmodified_since(label.updated_at) destroy_conditionally!(label)
status 204
label.destroy
end end
desc 'Update an existing label. At least one optional parameter is required.' do desc 'Update an existing label. At least one optional parameter is required.' do
......
...@@ -93,14 +93,13 @@ module API ...@@ -93,14 +93,13 @@ module API
end end
delete ":id/members/:user_id" do delete ":id/members/:user_id" do
source = find_source(source_type, params[:id]) source = find_source(source_type, params[:id])
# Ensure that memeber exists
member = source.members.find_by!(user_id: params[:user_id]) member = source.members.find_by!(user_id: params[:user_id])
check_unmodified_since(member.updated_at)
status 204 destroy_conditionally!(member) do
::Members::DestroyService.new(source, current_user, declared_params).execute ::Members::DestroyService.new(source, current_user, declared_params).execute
end end
end end
end end
end end
end
end end
...@@ -164,10 +164,8 @@ module API ...@@ -164,10 +164,8 @@ module API
merge_request = find_project_merge_request(params[:merge_request_iid]) merge_request = find_project_merge_request(params[:merge_request_iid])
authorize!(:destroy_merge_request, merge_request) authorize!(:destroy_merge_request, merge_request)
check_unmodified_since(merge_request.updated_at)
status 204 destroy_conditionally!(merge_request)
merge_request.destroy
end end
params do params do
......
...@@ -131,13 +131,13 @@ module API ...@@ -131,13 +131,13 @@ module API
note = user_project.notes.find(params[:note_id]) note = user_project.notes.find(params[:note_id])
authorize! :admin_note, note authorize! :admin_note, note
check_unmodified_since(note.updated_at)
status 204 destroy_conditionally!(note) do |note|
::Notes::DestroyService.new(user_project, current_user).execute(note) ::Notes::DestroyService.new(user_project, current_user).execute(note)
end end
end end
end end
end
helpers do helpers do
def find_project_noteable(noteables_str, noteable_id) def find_project_noteable(noteables_str, noteable_id)
......
...@@ -96,10 +96,7 @@ module API ...@@ -96,10 +96,7 @@ module API
delete ":id/hooks/:hook_id" do delete ":id/hooks/:hook_id" do
hook = user_project.hooks.find(params.delete(:hook_id)) hook = user_project.hooks.find(params.delete(:hook_id))
check_unmodified_since(hook.updated_at) destroy_conditionally!(hook)
status 204
hook.destroy
end end
end end
end end
......
...@@ -116,10 +116,8 @@ module API ...@@ -116,10 +116,8 @@ module API
not_found!('Snippet') unless snippet not_found!('Snippet') unless snippet
authorize! :admin_project_snippet, snippet authorize! :admin_project_snippet, snippet
check_unmodified_since(snippet.updated_at)
status 204 destroy_conditionally!(snippet)
snippet.destroy
end end
desc 'Get a raw project snippet' desc 'Get a raw project snippet'
......
...@@ -334,9 +334,10 @@ module API ...@@ -334,9 +334,10 @@ module API
desc 'Remove a project' desc 'Remove a project'
delete ":id" do delete ":id" do
authorize! :remove_project, user_project authorize! :remove_project, user_project
check_unmodified_since(user_project.updated_at)
destroy_conditionally!(user_project) do
::Projects::DestroyService.new(user_project, current_user, {}).async_execute ::Projects::DestroyService.new(user_project, current_user, {}).async_execute
end
accepted! accepted!
end end
......
...@@ -45,8 +45,10 @@ module API ...@@ -45,8 +45,10 @@ module API
end end
delete '/' do delete '/' do
authenticate_runner! authenticate_runner!
status 204
Ci::Runner.find_by_token(params[:token]).destroy runner = Ci::Runner.find_by_token(params[:token])
destroy_conditionally!(runner)
end end
desc 'Validates authentication credentials' do desc 'Validates authentication credentials' do
......
...@@ -79,10 +79,8 @@ module API ...@@ -79,10 +79,8 @@ module API
runner = get_runner(params[:id]) runner = get_runner(params[:id])
authenticate_delete_runner!(runner) authenticate_delete_runner!(runner)
check_unmodified_since(runner.updated_at)
status 204 destroy_conditionally!(runner)
runner.destroy!
end end
end end
...@@ -137,8 +135,7 @@ module API ...@@ -137,8 +135,7 @@ module API
runner = runner_project.runner runner = runner_project.runner
forbidden!("Only one project associated with the runner. Please remove the runner instead") if runner.projects.count == 1 forbidden!("Only one project associated with the runner. Please remove the runner instead") if runner.projects.count == 1
status 204 destroy_conditionally!(runner_project)
runner_project.destroy
end end
end end
......
...@@ -655,8 +655,8 @@ module API ...@@ -655,8 +655,8 @@ module API
end end
delete ":id/services/:service_slug" do delete ":id/services/:service_slug" do
service = user_project.find_or_initialize_service(params[:service_slug].underscore) service = user_project.find_or_initialize_service(params[:service_slug].underscore)
# Todo, not sure # Todo: Check if this done the right way
check_unmodified_since(service.updated_at) check_unmodified_since!(service.updated_at)
attrs = service_attributes(service).inject({}) do |hash, key| attrs = service_attributes(service).inject({}) do |hash, key|
hash.merge!(key => nil) hash.merge!(key => nil)
......
...@@ -122,10 +122,8 @@ module API ...@@ -122,10 +122,8 @@ module API
return not_found!('Snippet') unless snippet return not_found!('Snippet') unless snippet
authorize! :destroy_personal_snippet, snippet authorize! :destroy_personal_snippet, snippet
check_unmodified_since(snippet.updated_at)
status 204 destroy_conditionally!(snippet)
snippet.destroy
end end
desc 'Get a raw snippet' do desc 'Get a raw snippet' do
......
...@@ -66,10 +66,7 @@ module API ...@@ -66,10 +66,7 @@ module API
hook = SystemHook.find_by(id: params[:id]) hook = SystemHook.find_by(id: params[:id])
not_found!('System hook') unless hook not_found!('System hook') unless hook
check_unmodified_since(hook.updated_at) destroy_conditionally!(hook)
status 204
hook.destroy
end end
end end
end end
......
...@@ -140,10 +140,7 @@ module API ...@@ -140,10 +140,7 @@ module API
trigger = user_project.triggers.find(params.delete(:trigger_id)) trigger = user_project.triggers.find(params.delete(:trigger_id))
return not_found!('Trigger') unless trigger return not_found!('Trigger') unless trigger
check_unmodified_since(trigger.updated_at) destroy_conditionally!(trigger)
status 204
trigger.destroy
end end
end end
end end
......
...@@ -230,13 +230,7 @@ module API ...@@ -230,13 +230,7 @@ module API
key = user.keys.find_by(id: params[:key_id]) key = user.keys.find_by(id: params[:key_id])
not_found!('Key') unless key not_found!('Key') unless key
<<<<<<< HEAD destroy_conditionally!(key)
status 204
=======
check_unmodified_since(key.updated_at)
>>>>>>> API: Respect the 'If-Unmodified-Since' for delete endpoints
key.destroy
end end
desc 'Add an email address to a specified user. Available only for admins.' do desc 'Add an email address to a specified user. Available only for admins.' do
...@@ -292,14 +286,11 @@ module API ...@@ -292,14 +286,11 @@ module API
email = user.emails.find_by(id: params[:email_id]) email = user.emails.find_by(id: params[:email_id])
not_found!('Email') unless email not_found!('Email') unless email
<<<<<<< HEAD destroy_conditionally!(email) do |email|
Emails::DestroyService.new(user, email: email.email).execute Emails::DestroyService.new(current_user, email: email.email).execute
======= end
check_unmodified_since(email.updated_at)
email.destroy
user.update_secondary_emails! user.update_secondary_emails!
>>>>>>> API: Respect the 'If-Unmodified-Since' for delete endpoints
end end
desc 'Delete a user. Available only for admins.' do desc 'Delete a user. Available only for admins.' do
...@@ -315,14 +306,9 @@ module API ...@@ -315,14 +306,9 @@ module API
user = User.find_by(id: params[:id]) user = User.find_by(id: params[:id])
not_found!('User') unless user not_found!('User') unless user
<<<<<<< HEAD destroy_conditionally!(user) do
status 204
user.delete_async(deleted_by: current_user, params: params) user.delete_async(deleted_by: current_user, params: params)
======= end
check_unmodified_since(user.updated_at)
::Users::DestroyService.new(current_user).execute(user)
>>>>>>> API: Respect the 'If-Unmodified-Since' for delete endpoints
end end
desc 'Block a user. Available only for admins.' desc 'Block a user. Available only for admins.'
...@@ -500,10 +486,7 @@ module API ...@@ -500,10 +486,7 @@ module API
key = current_user.keys.find_by(id: params[:key_id]) key = current_user.keys.find_by(id: params[:key_id])
not_found!('Key') unless key not_found!('Key') unless key
check_unmodified_since(key.updated_at) destroy_conditionally!(key)
status 204
key.destroy
end end
desc "Get the currently authenticated user's email addresses" do desc "Get the currently authenticated user's email addresses" do
...@@ -554,11 +537,13 @@ module API ...@@ -554,11 +537,13 @@ module API
email = current_user.emails.find_by(id: params[:email_id]) email = current_user.emails.find_by(id: params[:email_id])
not_found!('Email') unless email not_found!('Email') unless email
<<<<<<< HEAD destroy_conditionally!(email) do |email|
status 204
Emails::DestroyService.new(current_user, email: email.email).execute Emails::DestroyService.new(current_user, email: email.email).execute
end end
current_user.update_secondary_emails!
end
desc 'Get a list of user activities' desc 'Get a list of user activities'
params do params do
optional :from, type: DateTime, default: 6.months.ago, desc: 'Date string in the format YEAR-MONTH-DAY' optional :from, type: DateTime, default: 6.months.ago, desc: 'Date string in the format YEAR-MONTH-DAY'
...@@ -572,12 +557,6 @@ module API ...@@ -572,12 +557,6 @@ module API
.reorder(last_activity_on: :asc) .reorder(last_activity_on: :asc)
present paginate(activities), with: Entities::UserActivity present paginate(activities), with: Entities::UserActivity
=======
check_unmodified_since(email.updated_at)
email.destroy
current_user.update_secondary_emails!
>>>>>>> API: Respect the 'If-Unmodified-Since' for delete endpoints
end end
end end
end end
......
...@@ -283,7 +283,7 @@ describe API::Tags do ...@@ -283,7 +283,7 @@ describe API::Tags do
it_behaves_like '404 response' do it_behaves_like '404 response' do
let(:request) { delete api(route, current_user) } let(:request) { delete api(route, current_user) }
let(:message) { 'No such tag' } let(:message) { '404 Tag Not Found' }
end end
end end
...@@ -394,7 +394,7 @@ describe API::Tags do ...@@ -394,7 +394,7 @@ describe API::Tags do
it_behaves_like '404 response' do it_behaves_like '404 response' do
let(:request) { put api(route, current_user), description: new_description } let(:request) { put api(route, current_user), description: new_description }
let(:message) { 'Tag does not exist' } let(:message) { '404 Tag Not Found' }
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment