1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
# frozen_string_literal: true
module API
class ProtectedBranches < ::API::Base
include PaginationParams
BRANCH_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(name: API::NO_SLASH_URL_PART_REGEX)
before { authorize_admin_project }
feature_category :source_code_management
helpers Helpers::ProtectedBranchesHelpers
params do
requires :id,
types: [String, Integer],
desc: 'The ID or URL-encoded path of the project',
documentation: { example: 'gitlab-org/gitlab' }
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc "Get a project's protected branches" do
success code: 200, model: Entities::ProtectedBranch
is_array true
failure [
{ code: 404, message: '404 Project Not Found' },
{ code: 401, message: '401 Unauthorized' }
]
end
params do
use :pagination
optional :search, type: String, desc: 'Search for a protected branch by name', documentation: { example: 'mai' }
end
# rubocop: disable CodeReuse/ActiveRecord
get ':id/protected_branches' do
protected_branches =
ProtectedBranchesFinder
.new(user_project, params)
.execute
.preload(:push_access_levels, :merge_access_levels)
present paginate(protected_branches), with: Entities::ProtectedBranch, project: user_project
end
# rubocop: enable CodeReuse/ActiveRecord
desc 'Get a single protected branch' do
success code: 200, model: Entities::ProtectedBranch
failure [
{ code: 404, message: '404 Project Not Found' },
{ code: 401, message: '401 Unauthorized' }
]
end
params do
requires :name, type: String, desc: 'The name of the branch or wildcard', documentation: { example: 'main' }
end
# rubocop: disable CodeReuse/ActiveRecord
get ':id/protected_branches/:name', requirements: BRANCH_ENDPOINT_REQUIREMENTS do
protected_branch = user_project.protected_branches.find_by!(name: params[:name])
present protected_branch, with: Entities::ProtectedBranch, project: user_project
end
# rubocop: enable CodeReuse/ActiveRecord
desc 'Protect a single branch' do
success code: 201, model: Entities::ProtectedBranch
failure [
{ code: 422, message: 'name is missing' },
{ code: 409, message: "Protected branch 'main' already exists" },
{ code: 404, message: '404 Project Not Found' },
{ code: 401, message: '401 Unauthorized' }
]
end
params do
requires :name, type: String, desc: 'The name of the protected branch', documentation: { example: 'main' }
optional :push_access_level, type: Integer,
values: ProtectedBranch::PushAccessLevel.allowed_access_levels,
desc: 'Access levels allowed to push (defaults: `40`, maintainer access level)'
optional :merge_access_level, type: Integer,
values: ProtectedBranch::MergeAccessLevel.allowed_access_levels,
desc: 'Access levels allowed to merge (defaults: `40`, maintainer access level)'
optional :allow_force_push, type: Boolean,
default: false,
desc: 'Allow force push for all users with push access.'
use :optional_params_ee
end
# rubocop: disable CodeReuse/ActiveRecord
post ':id/protected_branches' do
protected_branch = user_project.protected_branches.find_by(name: params[:name])
if protected_branch
conflict!("Protected branch '#{params[:name]}' already exists")
end
declared_params = declared_params(include_missing: false)
api_service = ::ProtectedBranches::ApiService.new(user_project, current_user, declared_params)
protected_branch = api_service.create
if protected_branch.persisted?
present protected_branch, with: Entities::ProtectedBranch, project: user_project
else
render_api_error!(protected_branch.errors.full_messages, 422)
end
end
# rubocop: enable CodeReuse/ActiveRecord
desc 'Update a protected branch' do
success code: 200, model: Entities::ProtectedBranch
failure [
{ code: 422, message: 'Push access levels access level has already been taken' },
{ code: 404, message: '404 Project Not Found' },
{ code: 401, message: '401 Unauthorized' }
]
end
params do
requires :name, type: String, desc: 'The name of the branch', documentation: { example: 'main' }
optional :allow_force_push, type: Boolean,
desc: 'Allow force push for all users with push access.'
use :optional_params_ee
end
# rubocop: disable CodeReuse/ActiveRecord
patch ':id/protected_branches/:name', requirements: BRANCH_ENDPOINT_REQUIREMENTS do
protected_branch = user_project.protected_branches.find_by!(name: params[:name])
declared_params = declared_params(include_missing: false)
api_service = ::ProtectedBranches::ApiService.new(user_project, current_user, declared_params)
protected_branch = api_service.update(protected_branch)
if protected_branch.valid?
present protected_branch, with: Entities::ProtectedBranch, project: user_project
else
render_api_error!(protected_branch.errors.full_messages, 422)
end
end
# rubocop: enable CodeReuse/ActiveRecord
desc 'Unprotect a single branch'
params do
requires :name, type: String, desc: 'The name of the protected branch', documentation: { example: 'main' }
end
desc 'Unprotect a single branch' do
success code: 204
failure [
{ code: 404, message: '404 Project Not Found' },
{ code: 401, message: '401 Unauthorized' }
]
end
# rubocop: disable CodeReuse/ActiveRecord
delete ':id/protected_branches/:name', requirements: BRANCH_ENDPOINT_REQUIREMENTS, urgency: :low do
protected_branch = user_project.protected_branches.find_by!(name: params[:name])
destroy_conditionally!(protected_branch) do
destroy_service = ::ProtectedBranches::DestroyService.new(user_project, current_user)
destroy_service.execute(protected_branch)
end
end
# rubocop: enable CodeReuse/ActiveRecord
end
end
end
API::ProtectedBranches.prepend_mod_with('API::ProtectedBranches')
|