projects.rb 14.7 KB
Newer Older
N
Nihad Abbasov 已提交
1 2 3 4 5 6
module Gitlab
  # Projects API
  class Projects < Grape::API
    before { authenticate! }

    resource :projects do
7 8 9 10 11 12 13 14 15
      helpers do
        def handle_project_member_errors(errors)
          if errors[:project_access].any?
            error!(errors[:project_access], 422)
          end
          not_found!
        end
      end

N
Nihad Abbasov 已提交
16 17 18 19 20
      # Get a projects list for authenticated user
      #
      # Example Request:
      #   GET /projects
      get do
21
        @projects = paginate current_user.authorized_projects
22
        present @projects, with: Entities::Project
N
Nihad Abbasov 已提交
23 24 25 26 27
      end

      # Get a single project
      #
      # Parameters:
28
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
29 30 31
      # Example Request:
      #   GET /projects/:id
      get ":id" do
32
        present user_project, with: Entities::Project
N
Nihad Abbasov 已提交
33 34
      end

35 36 37 38
      # Create new project
      #
      # Parameters:
      #   name (required) - name for new project
39 40 41 42 43 44
      #   description (optional) - short project description
      #   default_branch (optional) - 'master' by default
      #   issues_enabled (optional) - enabled by default
      #   wall_enabled (optional) - enabled by default
      #   merge_requests_enabled (optional) - enabled by default
      #   wiki_enabled (optional) - enabled by default
45 46 47
      # Example Request
      #   POST /projects
      post do
48
        error!("Name is required", 400) if !params.has_key? :name
49
        attrs = attributes_for_keys [:name,
50 51 52 53 54
                                    :description,
                                    :default_branch,
                                    :issues_enabled,
                                    :wall_enabled,
                                    :merge_requests_enabled,
A
Alex Denisov 已提交
55
                                    :wiki_enabled]
56

57
        @project = ::Projects::CreateContext.new(current_user, attrs).execute
58 59 60
        if @project.saved?
          present @project, with: Entities::Project
        else
61
          not_found!
62 63 64
        end
      end

N
Nihad Abbasov 已提交
65
      # Get a project team members
M
miks 已提交
66 67
      #
      # Parameters:
68
      #   id (required) - The ID of a project
V
Valeriy Sizov 已提交
69
      #   query         - Query string
M
miks 已提交
70
      # Example Request:
N
Nihad Abbasov 已提交
71 72
      #   GET /projects/:id/members
      get ":id/members" do
V
Valeriy Sizov 已提交
73 74 75 76 77
        if params[:query].present?
          @members = paginate user_project.users.where("username LIKE ?", "%#{params[:query]}%")
        else
          @members = paginate user_project.users
        end
N
Nihad Abbasov 已提交
78
        present @members, with: Entities::ProjectMember, project: user_project
M
miks 已提交
79 80
      end

N
Nihad Abbasov 已提交
81
      # Get a project team members
82 83
      #
      # Parameters:
84
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
85
      #   user_id (required) - The ID of a user
86
      # Example Request:
N
Nihad Abbasov 已提交
87 88 89 90 91 92 93 94 95
      #   GET /projects/:id/members/:user_id
      get ":id/members/:user_id" do
        @member = user_project.users.find params[:user_id]
        present @member, with: Entities::ProjectMember, project: user_project
      end

      # Add a new project team member
      #
      # Parameters:
96
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
97 98 99 100 101
      #   user_id (required) - The ID of a user
      #   access_level (required) - Project access level
      # Example Request:
      #   POST /projects/:id/members
      post ":id/members" do
R
randx 已提交
102
        authorize! :admin_project, user_project
N
Nihad Abbasov 已提交
103

104 105 106 107 108 109 110 111 112 113 114 115 116 117
        error!("User id not given", 400) if !params.has_key? :user_id
        error!("Access level not given", 400) if !params.has_key? :access_level

        # either the user is already a team member or a new one
        team_member = user_project.team_member_by_id(params[:user_id])
        if team_member.nil?
          team_member = user_project.users_projects.new(
            user_id: params[:user_id],
            project_access: params[:access_level]
          )
        end

        if team_member.save
          @member = team_member.user
N
Nihad Abbasov 已提交
118 119
          present @member, with: Entities::ProjectMember, project: user_project
        else
120
          handle_project_member_errors team_member.errors
N
Nihad Abbasov 已提交
121
        end
122 123
      end

N
Nihad Abbasov 已提交
124
      # Update project team member
M
miks 已提交
125 126
      #
      # Parameters:
127
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
128 129
      #   user_id (required) - The ID of a team member
      #   access_level (required) - Project access level
M
miks 已提交
130
      # Example Request:
N
Nihad Abbasov 已提交
131 132
      #   PUT /projects/:id/members/:user_id
      put ":id/members/:user_id" do
R
randx 已提交
133
        authorize! :admin_project, user_project
N
Nihad Abbasov 已提交
134

135 136 137 138 139 140
        team_member = user_project.users_projects.find_by_user_id(params[:user_id])
        error!("Access level not given", 400) if !params.has_key? :access_level
        error!("User can not be found", 404) if team_member.nil?

        if team_member.update_attributes(project_access: params[:access_level])
          @member = team_member.user
N
Nihad Abbasov 已提交
141 142
          present @member, with: Entities::ProjectMember, project: user_project
        else
143
          handle_project_member_errors team_member.errors
N
Nihad Abbasov 已提交
144
        end
M
miks 已提交
145 146
      end

N
Nihad Abbasov 已提交
147
      # Remove a team member from project
M
miks 已提交
148 149
      #
      # Parameters:
150
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
151
      #   user_id (required) - The ID of a team member
M
miks 已提交
152
      # Example Request:
N
Nihad Abbasov 已提交
153 154
      #   DELETE /projects/:id/members/:user_id
      delete ":id/members/:user_id" do
R
randx 已提交
155
        authorize! :admin_project, user_project
N
Nihad Abbasov 已提交
156
        users_project = user_project.users_projects.find_by_user_id params[:user_id]
157 158 159 160 161
        unless users_project.nil?
          users_project.destroy
        else
          {:message => "Access revoked", :id => params[:user_id].to_i}
        end
M
miks 已提交
162 163
      end

M
miks 已提交
164 165 166
      # Get project hooks
      #
      # Parameters:
167
      #   id (required) - The ID of a project
M
miks 已提交
168 169 170
      # Example Request:
      #   GET /projects/:id/hooks
      get ":id/hooks" do
M
miks 已提交
171
        authorize! :admin_project, user_project
M
miks 已提交
172 173 174
        @hooks = paginate user_project.hooks
        present @hooks, with: Entities::Hook
      end
S
Saito 已提交
175

J
jozefvaclavik 已提交
176 177 178
      # Get a project hook
      #
      # Parameters:
179
      #   id (required) - The ID of a project
J
jozefvaclavik 已提交
180 181 182 183 184 185 186
      #   hook_id (required) - The ID of a project hook
      # Example Request:
      #   GET /projects/:id/hooks/:hook_id
      get ":id/hooks/:hook_id" do
        @hook = user_project.hooks.find(params[:hook_id])
        present @hook, with: Entities::Hook
      end
S
Saito 已提交
187

M
miks 已提交
188 189 190 191

      # Add hook to project
      #
      # Parameters:
192
      #   id (required) - The ID of a project
M
miks 已提交
193 194 195 196
      #   url (required) - The hook URL
      # Example Request:
      #   POST /projects/:id/hooks
      post ":id/hooks" do
M
miks 已提交
197
        authorize! :admin_project, user_project
M
miks 已提交
198 199 200 201 202 203 204
        @hook = user_project.hooks.new({"url" => params[:url]})
        if @hook.save
          present @hook, with: Entities::Hook
        else
          error!({'message' => '404 Not found'}, 404)
        end
      end
S
Saito 已提交
205

J
jozefvaclavik 已提交
206 207 208
      # Update an existing project hook
      #
      # Parameters:
209
      #   id (required) - The ID of a project
J
jozefvaclavik 已提交
210 211 212 213 214 215 216 217
      #   hook_id (required) - The ID of a project hook
      #   url (required) - The hook URL
      # Example Request:
      #   PUT /projects/:id/hooks/:hook_id
      put ":id/hooks/:hook_id" do
        @hook = user_project.hooks.find(params[:hook_id])
        authorize! :admin_project, user_project

218
        error!("Url not given", 400) if !params.has_key? :url
J
jozefvaclavik 已提交
219

220
        attrs = attributes_for_keys [:url]
J
jozefvaclavik 已提交
221 222 223 224 225 226
        if @hook.update_attributes attrs
          present @hook, with: Entities::Hook
        else
          not_found!
        end
      end
M
miks 已提交
227 228 229 230

      # Delete project hook
      #
      # Parameters:
231
      #   id (required) - The ID of a project
M
miks 已提交
232 233 234 235
      #   hook_id (required) - The ID of hook to delete
      # Example Request:
      #   DELETE /projects/:id/hooks
      delete ":id/hooks" do
M
miks 已提交
236
        authorize! :admin_project, user_project
M
miks 已提交
237 238 239 240
        @hook = user_project.hooks.find(params[:hook_id])
        @hook.destroy
      end

N
Nihad Abbasov 已提交
241 242 243
      # Get a project repository branches
      #
      # Parameters:
244
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
245 246 247
      # Example Request:
      #   GET /projects/:id/repository/branches
      get ":id/repository/branches" do
248
        present user_project.repo.heads.sort_by(&:name), with: Entities::RepoObject, project: user_project
N
Nihad Abbasov 已提交
249 250
      end

251 252 253
      # Get a single branch
      #
      # Parameters:
254
      #   id (required) - The ID of a project
255
      #   branch (required) - The name of the branch
256
      # Example Request:
257 258 259
      #   GET /projects/:id/repository/branches/:branch
      get ":id/repository/branches/:branch" do
        @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
        present @branch, with: Entities::RepoObject, project: user_project
      end

      # Protect a single branch
      #
      # Parameters:
      #   id (required) - The ID of a project
      #   branch (required) - The name of the branch
      # Example Request:
      #   PUT /projects/:id/repository/branches/:branch/protect
      put ":id/repository/branches/:branch/protect" do
        @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
        protected = user_project.protected_branches.find_by_name(@branch.name)

        unless protected
          user_project.protected_branches.create(:name => @branch.name)
        end

        present @branch, with: Entities::RepoObject, project: user_project
      end

      # Unprotect a single branch
      #
      # Parameters:
      #   id (required) - The ID of a project
      #   branch (required) - The name of the branch
      # Example Request:
      #   PUT /projects/:id/repository/branches/:branch/unprotect
      put ":id/repository/branches/:branch/unprotect" do
        @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
        protected = user_project.protected_branches.find_by_name(@branch.name)

        if protected
          protected.destroy
        end

        present @branch, with: Entities::RepoObject, project: user_project
297 298
      end

N
Nihad Abbasov 已提交
299 300 301
      # Get a project repository tags
      #
      # Parameters:
302
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
303 304 305
      # Example Request:
      #   GET /projects/:id/repository/tags
      get ":id/repository/tags" do
306
        present user_project.repo.tags.sort_by(&:name).reverse, with: Entities::RepoObject
N
Nihad Abbasov 已提交
307
      end
N
Nihad Abbasov 已提交
308

309 310 311
      # Get a project repository commits
      #
      # Parameters:
312
      #   id (required) - The ID of a project
313 314 315 316 317 318 319 320 321 322
      #   ref_name (optional) - The name of a repository branch or tag
      # Example Request:
      #   GET /projects/:id/repository/commits
      get ":id/repository/commits" do
        authorize! :download_code, user_project

        page = params[:page] || 0
        per_page = params[:per_page] || 20
        ref = params[:ref_name] || user_project.try(:default_branch) || 'master'

D
Dmitriy Zaporozhets 已提交
323
        commits = user_project.repository.commits(ref, nil, per_page, page * per_page)
324 325 326
        present CommitDecorator.decorate(commits), with: Entities::RepoCommit
      end

N
Nihad Abbasov 已提交
327 328 329
      # Get a project snippets
      #
      # Parameters:
330
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
331 332 333 334 335 336
      # Example Request:
      #   GET /projects/:id/snippets
      get ":id/snippets" do
        present paginate(user_project.snippets), with: Entities::ProjectSnippet
      end

N
Nihad Abbasov 已提交
337 338 339
      # Get a project snippet
      #
      # Parameters:
340
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
341 342 343 344
      #   snippet_id (required) - The ID of a project snippet
      # Example Request:
      #   GET /projects/:id/snippets/:snippet_id
      get ":id/snippets/:snippet_id" do
N
Nihad Abbasov 已提交
345
        @snippet = user_project.snippets.find(params[:snippet_id])
346
        present @snippet, with: Entities::ProjectSnippet
N
Nihad Abbasov 已提交
347 348 349 350 351
      end

      # Create a new project snippet
      #
      # Parameters:
352
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
353 354 355 356 357 358 359
      #   title (required) - The title of a snippet
      #   file_name (required) - The name of a snippet file
      #   lifetime (optional) - The expiration date of a snippet
      #   code (required) - The content of a snippet
      # Example Request:
      #   POST /projects/:id/snippets
      post ":id/snippets" do
360 361
        authorize! :write_snippet, user_project

A
Alex Denisov 已提交
362
        attrs = attributes_for_keys [:title, :file_name]
A
Alex Denisov 已提交
363 364 365
        attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
        attrs[:content] = params[:code] if params[:code].present?
        @snippet = user_project.snippets.new attrs
N
Nihad Abbasov 已提交
366 367 368
        @snippet.author = current_user

        if @snippet.save
369
          present @snippet, with: Entities::ProjectSnippet
N
Nihad Abbasov 已提交
370
        else
371
          not_found!
N
Nihad Abbasov 已提交
372 373 374
        end
      end

375 376 377
      # Update an existing project snippet
      #
      # Parameters:
378
      #   id (required) - The ID of a project
379 380 381 382 383 384 385 386
      #   snippet_id (required) - The ID of a project snippet
      #   title (optional) - The title of a snippet
      #   file_name (optional) - The name of a snippet file
      #   lifetime (optional) - The expiration date of a snippet
      #   code (optional) - The content of a snippet
      # Example Request:
      #   PUT /projects/:id/snippets/:snippet_id
      put ":id/snippets/:snippet_id" do
N
Nihad Abbasov 已提交
387
        @snippet = user_project.snippets.find(params[:snippet_id])
R
randx 已提交
388 389
        authorize! :modify_snippet, @snippet

A
Alex Denisov 已提交
390
        attrs = attributes_for_keys [:title, :file_name]
A
Alex Denisov 已提交
391 392
        attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
        attrs[:content] = params[:code] if params[:code].present?
393

A
Alex Denisov 已提交
394
        if @snippet.update_attributes attrs
395
          present @snippet, with: Entities::ProjectSnippet
396
        else
397
          not_found!
398 399 400
        end
      end

N
Nihad Abbasov 已提交
401 402 403
      # Delete a project snippet
      #
      # Parameters:
404
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
405 406 407 408
      #   snippet_id (required) - The ID of a project snippet
      # Example Request:
      #   DELETE /projects/:id/snippets/:snippet_id
      delete ":id/snippets/:snippet_id" do
N
Nihad Abbasov 已提交
409
        @snippet = user_project.snippets.find(params[:snippet_id])
R
randx 已提交
410 411
        authorize! :modify_snippet, @snippet

N
Nihad Abbasov 已提交
412 413
        @snippet.destroy
      end
414 415 416 417

      # Get a raw project snippet
      #
      # Parameters:
418
      #   id (required) - The ID of a project
419 420 421 422
      #   snippet_id (required) - The ID of a project snippet
      # Example Request:
      #   GET /projects/:id/snippets/:snippet_id/raw
      get ":id/snippets/:snippet_id/raw" do
N
Nihad Abbasov 已提交
423
        @snippet = user_project.snippets.find(params[:snippet_id])
424
        content_type 'text/plain'
425 426
        present @snippet.content
      end
427 428 429 430

      # Get a raw file contents
      #
      # Parameters:
431
      #   id (required) - The ID of a project
432
      #   sha (required) - The commit or branch name
433 434 435 436
      #   filepath (required) - The path to the file to display
      # Example Request:
      #   GET /projects/:id/repository/commits/:sha/blob
      get ":id/repository/commits/:sha/blob" do
437 438
        authorize! :download_code, user_project

439 440
        ref = params[:sha]

D
Dmitriy Zaporozhets 已提交
441
        commit = user_project.repository.commit ref
442
        not_found! "Commit" unless commit
443

D
Dmitriy Zaporozhets 已提交
444
        tree = Tree.new commit.tree, ref, params[:filepath]
445
        not_found! "File" unless tree.try(:tree)
446

S
Saito 已提交
447
        content_type tree.mime_type
448 449 450
        present tree.data
      end

N
Nihad Abbasov 已提交
451 452 453
    end
  end
end