summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2014-05-23 06:06:22 +0000
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2014-05-23 06:06:22 +0000
commit9e6466c78442075e0f8fb8fe317ffe53dfcb5a95 (patch)
treeb36877c3b8957449210bb0739d201a68c3c6e1f0
parenteee14a0c740b53dfba50e1b091d4017ada92ee97 (diff)
parentb9d1fc2f3bdebe541795d6ef6e94da9e98b043d3 (diff)
downloadgitlab-ce-9e6466c78442075e0f8fb8fe317ffe53dfcb5a95.tar.gz
Merge branch 'api-remove-branch' into 'master'
New rules for protected branches This MR change permissions logic for branch removal. Changes listed below: Before * developer can remove branch with terminal but not in UI * masters can remove any branch with UI even protected one * force-push to protected branch is not allowed but remove is allowed After * none can force push or remove protected branches * developers and masters can remove normal branches with console and UI
-rw-r--r--app/controllers/projects/branches_controller.rb9
-rw-r--r--app/helpers/branches_helper.rb11
-rw-r--r--app/services/delete_branch_service.rb46
-rw-r--r--app/views/projects/branches/_branch.html.haml4
-rw-r--r--app/views/projects/protected_branches/index.html.haml10
-rw-r--r--lib/api/branches.rb12
-rw-r--r--lib/gitlab/git_access.rb20
7 files changed, 90 insertions, 22 deletions
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index 6a6cbe48184..00811f17adb 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -4,8 +4,7 @@ class Projects::BranchesController < Projects::ApplicationController
before_filter :require_non_empty_project
before_filter :authorize_code_access!
- before_filter :authorize_push!, only: [:create]
- before_filter :authorize_admin_project!, only: [:destroy]
+ before_filter :authorize_push!, only: [:create, :destroy]
def index
@branches = Kaminari.paginate_array(@repository.branches).page(params[:page]).per(30)
@@ -22,11 +21,7 @@ class Projects::BranchesController < Projects::ApplicationController
end
def destroy
- branch = @repository.find_branch(params[:id])
-
- if branch && @repository.rm_branch(branch.name)
- Event.create_ref_event(@project, current_user, branch, 'rm')
- end
+ DeleteBranchService.new.execute(project, params[:id], current_user)
respond_to do |format|
format.html { redirect_to project_branches_path(@project) }
diff --git a/app/helpers/branches_helper.rb b/app/helpers/branches_helper.rb
new file mode 100644
index 00000000000..e08ffccb94c
--- /dev/null
+++ b/app/helpers/branches_helper.rb
@@ -0,0 +1,11 @@
+module BranchesHelper
+ def can_remove_branch?(project, branch_name)
+ if project.protected_branch? branch_name
+ false
+ elsif branch_name == project.repository.root_ref
+ false
+ else
+ can?(current_user, :push_code, project)
+ end
+ end
+end
diff --git a/app/services/delete_branch_service.rb b/app/services/delete_branch_service.rb
new file mode 100644
index 00000000000..ce2d8093dff
--- /dev/null
+++ b/app/services/delete_branch_service.rb
@@ -0,0 +1,46 @@
+class DeleteBranchService
+ def execute(project, branch_name, current_user)
+ repository = project.repository
+ branch = repository.find_branch(branch_name)
+
+ # No such branch
+ unless branch
+ return error('No such branch')
+ end
+
+ if branch_name == repository.root_ref
+ return error('Cannot remove HEAD branch')
+ end
+
+ # Dont allow remove of protected branch
+ if project.protected_branch?(branch_name)
+ return error('Protected branch cant be removed')
+ end
+
+ # Dont allow user to remove branch if he is not allowed to push
+ unless current_user.can?(:push_code, project)
+ return error('You dont have push access to repo')
+ end
+
+ if repository.rm_branch(branch_name)
+ Event.create_ref_event(project, current_user, branch, 'rm')
+ success('Branch was removed')
+ else
+ return error('Failed to remove branch')
+ end
+ end
+
+ def error(message)
+ {
+ message: message,
+ state: :error
+ }
+ end
+
+ def success(message)
+ {
+ message: message,
+ state: :success
+ }
+ end
+end
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index f0731977098..87f4dd88c27 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -16,8 +16,8 @@
%i.icon-copy
Compare
- - if can?(current_user, :admin_project, @project) && branch.name != @repository.root_ref
- = link_to project_branch_path(@project, branch.name), class: 'btn btn-grouped btn-small remove-row', method: :delete, data: { confirm: 'Removed branch cannot be restored. Are you sure?'}, remote: true do
+ - if can_remove_branch?(@project, branch.name)
+ = link_to project_branch_path(@project, branch.name), class: 'btn btn-grouped btn-small btn-remove remove-row', method: :delete, data: { confirm: 'Removed branch cannot be restored. Are you sure?'}, remote: true do
%i.icon-trash
- if commit
diff --git a/app/views/projects/protected_branches/index.html.haml b/app/views/projects/protected_branches/index.html.haml
index 4a6e8943a9f..e9f67b671bf 100644
--- a/app/views/projects/protected_branches/index.html.haml
+++ b/app/views/projects/protected_branches/index.html.haml
@@ -4,12 +4,12 @@
= render "projects/branches/filter"
.col-md-9
.bs-callout.bs-callout-info
- %p Protected branches designed to prevent push for all except #{link_to "masters", help_permissions_path, class: "vlink"}.
- %p This ability allows:
+ %p Protected branches designed to
%ul
- %li keep stable branches secured
- %li forced code review before merge to protected branches
- %li prevents branch from force push
+ %li prevent push for all except #{link_to "masters", help_permissions_path, class: "vlink"}.
+ %li prevent branch from force push
+ %li prevent branch from removal
+ %p This ability allows to keep stable branches secured and force code review before merge to protected branches
%p Read more about project permissions #{link_to "here", help_permissions_path, class: "underlined-link"}
- if can? current_user, :admin_project, @project
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index d54f9371fbe..32597eb94c4 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -84,6 +84,18 @@ module API
present @branch, with: Entities::RepoObject, project: user_project
end
+
+ # Delete branch
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # branch (required) - The name of the branch
+ # Example Request:
+ # DELETE /projects/:id/repository/branches/:branch
+ delete ":id/repository/branches/:branch" do
+ authorize_push_project
+ DeleteBranchService.new.execute(user_project, params[:branch], current_user)
+ end
end
end
end
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index 4f49ca4189e..2f8b55aaca0 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -44,14 +44,18 @@ module Gitlab
def push_allowed?(user, project, ref, oldrev, newrev, forced_push)
if user && user_allowed?(user)
action = if project.protected_branch?(ref)
- if forced_push.to_s == 'true'
- :force_push_code_to_protected_branches
- else
- :push_code_to_protected_branches
- end
- else
- :push_code
- end
+ # we dont allow force push to protected branch
+ if forced_push.to_s == 'true'
+ :force_push_code_to_protected_branches
+ # and we dont allow remove of protected branch
+ elsif newrev =~ /0000000/
+ :remove_protected_branches
+ else
+ :push_code_to_protected_branches
+ end
+ else
+ :push_code
+ end
user.can?(action, project)
else
false