projects.rb 14.9 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
198 199 200

        error!("Url not given", 400) unless params.has_key? :url

M
miks 已提交
201 202 203 204
        @hook = user_project.hooks.new({"url" => params[:url]})
        if @hook.save
          present @hook, with: Entities::Hook
        else
205
          not_found!
M
miks 已提交
206 207
        end
      end
S
Saito 已提交
208

J
jozefvaclavik 已提交
209 210 211
      # Update an existing project hook
      #
      # Parameters:
212
      #   id (required) - The ID of a project
J
jozefvaclavik 已提交
213 214 215 216 217 218 219 220
      #   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

221
        error!("Url not given", 400) unless params.has_key? :url
J
jozefvaclavik 已提交
222

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

      # Delete project hook
      #
      # Parameters:
234
      #   id (required) - The ID of a project
M
miks 已提交
235 236 237 238
      #   hook_id (required) - The ID of hook to delete
      # Example Request:
      #   DELETE /projects/:id/hooks
      delete ":id/hooks" do
M
miks 已提交
239
        authorize! :admin_project, user_project
240 241 242 243 244 245 246
        error!("Hook id not given", 400) unless params.has_key? :hook_id

        begin
          @hook = ProjectHook.find(params[:hook_id])
          @hook.destroy
        rescue
        end
M
miks 已提交
247 248
      end

N
Nihad Abbasov 已提交
249 250 251
      # Get a project repository branches
      #
      # Parameters:
252
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
253 254 255
      # Example Request:
      #   GET /projects/:id/repository/branches
      get ":id/repository/branches" do
256
        present user_project.repo.heads.sort_by(&:name), with: Entities::RepoObject, project: user_project
N
Nihad Abbasov 已提交
257 258
      end

259 260 261
      # Get a single branch
      #
      # Parameters:
262
      #   id (required) - The ID of a project
263
      #   branch (required) - The name of the branch
264
      # Example Request:
265 266 267
      #   GET /projects/:id/repository/branches/:branch
      get ":id/repository/branches/:branch" do
        @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
268
        not_found!("Branch does not exist") if @branch.nil?
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 297 298 299 300 301 302 303 304 305
        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
306 307
      end

N
Nihad Abbasov 已提交
308 309 310
      # Get a project repository tags
      #
      # Parameters:
311
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
312 313 314
      # Example Request:
      #   GET /projects/:id/repository/tags
      get ":id/repository/tags" do
315
        present user_project.repo.tags.sort_by(&:name).reverse, with: Entities::RepoObject
N
Nihad Abbasov 已提交
316
      end
N
Nihad Abbasov 已提交
317

318 319 320
      # Get a project repository commits
      #
      # Parameters:
321
      #   id (required) - The ID of a project
322 323 324 325 326 327 328 329 330 331
      #   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 已提交
332
        commits = user_project.repository.commits(ref, nil, per_page, page * per_page)
333 334 335
        present CommitDecorator.decorate(commits), with: Entities::RepoCommit
      end

N
Nihad Abbasov 已提交
336 337 338
      # Get a project snippets
      #
      # Parameters:
339
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
340 341 342 343 344 345
      # Example Request:
      #   GET /projects/:id/snippets
      get ":id/snippets" do
        present paginate(user_project.snippets), with: Entities::ProjectSnippet
      end

N
Nihad Abbasov 已提交
346 347 348
      # Get a project snippet
      #
      # Parameters:
349
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
350 351 352 353
      #   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 已提交
354
        @snippet = user_project.snippets.find(params[:snippet_id])
355
        present @snippet, with: Entities::ProjectSnippet
N
Nihad Abbasov 已提交
356 357 358 359 360
      end

      # Create a new project snippet
      #
      # Parameters:
361
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
362 363 364 365 366 367 368
      #   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
369 370
        authorize! :write_snippet, user_project

A
Alex Denisov 已提交
371
        attrs = attributes_for_keys [:title, :file_name]
A
Alex Denisov 已提交
372 373 374
        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 已提交
375 376 377
        @snippet.author = current_user

        if @snippet.save
378
          present @snippet, with: Entities::ProjectSnippet
N
Nihad Abbasov 已提交
379
        else
380
          not_found!
N
Nihad Abbasov 已提交
381 382 383
        end
      end

384 385 386
      # Update an existing project snippet
      #
      # Parameters:
387
      #   id (required) - The ID of a project
388 389 390 391 392 393 394 395
      #   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 已提交
396
        @snippet = user_project.snippets.find(params[:snippet_id])
R
randx 已提交
397 398
        authorize! :modify_snippet, @snippet

A
Alex Denisov 已提交
399
        attrs = attributes_for_keys [:title, :file_name]
A
Alex Denisov 已提交
400 401
        attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
        attrs[:content] = params[:code] if params[:code].present?
402

A
Alex Denisov 已提交
403
        if @snippet.update_attributes attrs
404
          present @snippet, with: Entities::ProjectSnippet
405
        else
406
          not_found!
407 408 409
        end
      end

N
Nihad Abbasov 已提交
410 411 412
      # Delete a project snippet
      #
      # Parameters:
413
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
414 415 416 417
      #   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 已提交
418
        @snippet = user_project.snippets.find(params[:snippet_id])
R
randx 已提交
419 420
        authorize! :modify_snippet, @snippet

N
Nihad Abbasov 已提交
421 422
        @snippet.destroy
      end
423 424 425 426

      # Get a raw project snippet
      #
      # Parameters:
427
      #   id (required) - The ID of a project
428 429 430 431
      #   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 已提交
432
        @snippet = user_project.snippets.find(params[:snippet_id])
433
        content_type 'text/plain'
434 435
        present @snippet.content
      end
436 437 438 439

      # Get a raw file contents
      #
      # Parameters:
440
      #   id (required) - The ID of a project
441
      #   sha (required) - The commit or branch name
442 443 444 445
      #   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
446 447
        authorize! :download_code, user_project

448 449
        ref = params[:sha]

D
Dmitriy Zaporozhets 已提交
450
        commit = user_project.repository.commit ref
451
        not_found! "Commit" unless commit
452

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

S
Saito 已提交
456
        content_type tree.mime_type
457 458 459
        present tree.data
      end

N
Nihad Abbasov 已提交
460 461 462
    end
  end
end