projects.rb 12.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
module Gitlab
  # Projects API
  class Projects < Grape::API
    before { authenticate! }

    resource :projects do
      # Get a projects list for authenticated user
      #
      # Example Request:
      #   GET /projects
      get do
Nihad Abbasov's avatar
Nihad Abbasov committed
12
        @projects = paginate current_user.projects
13
        present @projects, with: Entities::Project
14 15 16 17 18
      end

      # Get a single project
      #
      # Parameters:
Nihad Abbasov's avatar
Nihad Abbasov committed
19
      #   id (required) - The ID or code name of a project
20 21 22
      # Example Request:
      #   GET /projects/:id
      get ":id" do
23
        present user_project, with: Entities::Project
24 25
      end

26 27 28 29
      # Create new project
      #
      # Parameters:
      #   name (required) - name for new project
Alex Denisov's avatar
Alex Denisov committed
30 31
      #   code (optional) - code for new project, uses project name if not set
      #   path (optional) - path for new project, uses project name if not set
32 33 34 35 36 37
      #   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
38 39 40
      # Example Request
      #   POST /projects
      post do
Alex Denisov's avatar
Alex Denisov committed
41 42
        params[:code] ||= params[:name]
        params[:path] ||= params[:name]
43 44 45 46 47 48 49 50
        attrs = attributes_for_keys [:code,
                                    :path,
                                    :name,
                                    :description,
                                    :default_branch,
                                    :issues_enabled,
                                    :wall_enabled,
                                    :merge_requests_enabled,
Alex Denisov's avatar
Alex Denisov committed
51 52
                                    :wiki_enabled]
        @project = Project.create_by_user(attrs, current_user)
53 54 55
        if @project.saved?
          present @project, with: Entities::Project
        else
56
          not_found!
57 58 59
        end
      end

60
      # Get a project team members
miks's avatar
miks committed
61 62 63 64
      #
      # Parameters:
      #   id (required) - The ID or code name of a project
      # Example Request:
65 66 67 68
      #   GET /projects/:id/members
      get ":id/members" do
        @members = paginate user_project.users
        present @members, with: Entities::ProjectMember, project: user_project
miks's avatar
miks committed
69 70
      end

71
      # Get a project team members
72 73 74
      #
      # Parameters:
      #   id (required) - The ID or code name of a project
75
      #   user_id (required) - The ID of a user
76
      # Example Request:
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
      #   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:
      #   id (required) - The ID or code name of a project
      #   user_id (required) - The ID of a user
      #   access_level (required) - Project access level
      # Example Request:
      #   POST /projects/:id/members
      post ":id/members" do
randx's avatar
randx committed
92
        authorize! :admin_project, user_project
93 94 95 96 97 98 99 100 101 102 103
        users_project = user_project.users_projects.new(
          user_id: params[:user_id],
          project_access: params[:access_level]
        )

        if users_project.save
          @member = users_project.user
          present @member, with: Entities::ProjectMember, project: user_project
        else
          not_found!
        end
104 105
      end

106
      # Update project team member
miks's avatar
miks committed
107 108 109
      #
      # Parameters:
      #   id (required) - The ID or code name of a project
110 111
      #   user_id (required) - The ID of a team member
      #   access_level (required) - Project access level
miks's avatar
miks committed
112
      # Example Request:
113 114
      #   PUT /projects/:id/members/:user_id
      put ":id/members/:user_id" do
randx's avatar
randx committed
115
        authorize! :admin_project, user_project
116 117 118 119 120 121 122 123
        users_project = user_project.users_projects.find_by_user_id params[:user_id]

        if users_project.update_attributes(project_access: params[:access_level])
          @member = users_project.user
          present @member, with: Entities::ProjectMember, project: user_project
        else
          not_found!
        end
miks's avatar
miks committed
124 125
      end

126
      # Remove a team member from project
miks's avatar
miks committed
127 128 129
      #
      # Parameters:
      #   id (required) - The ID or code name of a project
130
      #   user_id (required) - The ID of a team member
miks's avatar
miks committed
131
      # Example Request:
132 133
      #   DELETE /projects/:id/members/:user_id
      delete ":id/members/:user_id" do
randx's avatar
randx committed
134
        authorize! :admin_project, user_project
135 136
        users_project = user_project.users_projects.find_by_user_id params[:user_id]
        users_project.destroy
miks's avatar
miks committed
137 138
      end

miks's avatar
miks committed
139 140 141 142 143 144 145
      # Get project hooks
      #
      # Parameters:
      #   id (required) - The ID or code name of a project
      # Example Request:
      #   GET /projects/:id/hooks
      get ":id/hooks" do
miks's avatar
miks committed
146
        authorize! :admin_project, user_project
miks's avatar
miks committed
147 148 149
        @hooks = paginate user_project.hooks
        present @hooks, with: Entities::Hook
      end
Saito's avatar
Saito committed
150

jozefvaclavik's avatar
jozefvaclavik committed
151 152 153 154 155 156 157 158 159 160 161
      # Get a project hook
      #
      # Parameters:
      #   id (required) - The ID or code name of a project
      #   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
Saito's avatar
Saito committed
162

miks's avatar
miks committed
163 164 165 166 167 168 169 170 171

      # Add hook to project
      #
      # Parameters:
      #   id (required) - The ID or code name of a project
      #   url (required) - The hook URL
      # Example Request:
      #   POST /projects/:id/hooks
      post ":id/hooks" do
miks's avatar
miks committed
172
        authorize! :admin_project, user_project
miks's avatar
miks committed
173 174 175 176 177 178 179
        @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
Saito's avatar
Saito committed
180

jozefvaclavik's avatar
jozefvaclavik committed
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
      # Update an existing project hook
      #
      # Parameters:
      #   id (required) - The ID or code name of a project
      #   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

        attrs = attributes_for_keys [:url]

        if @hook.update_attributes attrs
          present @hook, with: Entities::Hook
        else
          not_found!
        end
      end
miks's avatar
miks committed
201 202 203 204 205 206 207 208 209

      # Delete project hook
      #
      # Parameters:
      #   id (required) - The ID or code name of a project
      #   hook_id (required) - The ID of hook to delete
      # Example Request:
      #   DELETE /projects/:id/hooks
      delete ":id/hooks" do
miks's avatar
miks committed
210
        authorize! :admin_project, user_project
miks's avatar
miks committed
211 212 213 214
        @hook = user_project.hooks.find(params[:hook_id])
        @hook.destroy
      end

215 216 217
      # Get a project repository branches
      #
      # Parameters:
Nihad Abbasov's avatar
Nihad Abbasov committed
218
      #   id (required) - The ID or code name of a project
219 220 221
      # Example Request:
      #   GET /projects/:id/repository/branches
      get ":id/repository/branches" do
222
        present user_project.repo.heads.sort_by(&:name), with: Entities::RepoObject
223 224
      end

225 226 227 228
      # Get a single branch
      #
      # Parameters:
      #   id (required) - The ID or code name of a project
229
      #   branch (required) - The name of the branch
230
      # Example Request:
231 232 233
      #   GET /projects/:id/repository/branches/:branch
      get ":id/repository/branches/:branch" do
        @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
234
        present @branch, with: Entities::RepoObject
235 236
      end

237 238 239
      # Get a project repository tags
      #
      # Parameters:
Nihad Abbasov's avatar
Nihad Abbasov committed
240
      #   id (required) - The ID or code name of a project
241 242 243
      # Example Request:
      #   GET /projects/:id/repository/tags
      get ":id/repository/tags" do
244
        present user_project.repo.tags.sort_by(&:name).reverse, with: Entities::RepoObject
245
      end
Nihad Abbasov's avatar
Nihad Abbasov committed
246

247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
      # Get a project repository commits
      #
      # Parameters:
      #   id (required) - The ID or code name of a project
      #   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'

        commits = user_project.commits(ref, nil, per_page, page * per_page)
        present CommitDecorator.decorate(commits), with: Entities::RepoCommit
      end

265 266 267 268 269 270 271 272 273 274
      # Get a project snippets
      #
      # Parameters:
      #   id (required) - The ID or code name of a project
      # Example Request:
      #   GET /projects/:id/snippets
      get ":id/snippets" do
        present paginate(user_project.snippets), with: Entities::ProjectSnippet
      end

Nihad Abbasov's avatar
Nihad Abbasov committed
275 276 277
      # Get a project snippet
      #
      # Parameters:
Nihad Abbasov's avatar
Nihad Abbasov committed
278
      #   id (required) - The ID or code name of a project
Nihad Abbasov's avatar
Nihad Abbasov committed
279 280 281 282
      #   snippet_id (required) - The ID of a project snippet
      # Example Request:
      #   GET /projects/:id/snippets/:snippet_id
      get ":id/snippets/:snippet_id" do
Nihad Abbasov's avatar
Nihad Abbasov committed
283
        @snippet = user_project.snippets.find(params[:snippet_id])
284
        present @snippet, with: Entities::ProjectSnippet
Nihad Abbasov's avatar
Nihad Abbasov committed
285 286 287 288 289
      end

      # Create a new project snippet
      #
      # Parameters:
Nihad Abbasov's avatar
Nihad Abbasov committed
290
      #   id (required) - The ID or code name of a project
Nihad Abbasov's avatar
Nihad Abbasov committed
291 292 293 294 295 296 297
      #   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
298 299
        authorize! :write_snippet, user_project

Alex Denisov's avatar
Alex Denisov committed
300
        attrs = attributes_for_keys [:title, :file_name]
Alex Denisov's avatar
Alex Denisov committed
301 302 303
        attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
        attrs[:content] = params[:code] if params[:code].present?
        @snippet = user_project.snippets.new attrs
Nihad Abbasov's avatar
Nihad Abbasov committed
304 305 306
        @snippet.author = current_user

        if @snippet.save
307
          present @snippet, with: Entities::ProjectSnippet
Nihad Abbasov's avatar
Nihad Abbasov committed
308
        else
309
          not_found!
Nihad Abbasov's avatar
Nihad Abbasov committed
310 311 312
        end
      end

313 314 315
      # Update an existing project snippet
      #
      # Parameters:
Nihad Abbasov's avatar
Nihad Abbasov committed
316
      #   id (required) - The ID or code name of a project
317 318 319 320 321 322 323 324
      #   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
Nihad Abbasov's avatar
Nihad Abbasov committed
325
        @snippet = user_project.snippets.find(params[:snippet_id])
randx's avatar
randx committed
326 327
        authorize! :modify_snippet, @snippet

Alex Denisov's avatar
Alex Denisov committed
328
        attrs = attributes_for_keys [:title, :file_name]
Alex Denisov's avatar
Alex Denisov committed
329 330
        attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
        attrs[:content] = params[:code] if params[:code].present?
331

Alex Denisov's avatar
Alex Denisov committed
332
        if @snippet.update_attributes attrs
333
          present @snippet, with: Entities::ProjectSnippet
334
        else
335
          not_found!
336 337 338
        end
      end

Nihad Abbasov's avatar
Nihad Abbasov committed
339 340 341
      # Delete a project snippet
      #
      # Parameters:
Nihad Abbasov's avatar
Nihad Abbasov committed
342
      #   id (required) - The ID or code name of a project
Nihad Abbasov's avatar
Nihad Abbasov committed
343 344 345 346
      #   snippet_id (required) - The ID of a project snippet
      # Example Request:
      #   DELETE /projects/:id/snippets/:snippet_id
      delete ":id/snippets/:snippet_id" do
Nihad Abbasov's avatar
Nihad Abbasov committed
347
        @snippet = user_project.snippets.find(params[:snippet_id])
randx's avatar
randx committed
348 349
        authorize! :modify_snippet, @snippet

Nihad Abbasov's avatar
Nihad Abbasov committed
350 351
        @snippet.destroy
      end
352 353 354 355

      # Get a raw project snippet
      #
      # Parameters:
Nihad Abbasov's avatar
Nihad Abbasov committed
356
      #   id (required) - The ID or code name of a project
357 358 359 360
      #   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
Nihad Abbasov's avatar
Nihad Abbasov committed
361
        @snippet = user_project.snippets.find(params[:snippet_id])
362
        content_type 'text/plain'
363 364
        present @snippet.content
      end
365 366 367 368 369

      # Get a raw file contents
      #
      # Parameters:
      #   id (required) - The ID or code name of a project
370
      #   sha (required) - The commit or branch name
371 372 373 374
      #   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
375 376
        authorize! :download_code, user_project

377 378 379
        ref = params[:sha]

        commit = user_project.commit ref
380
        not_found! "Commit" unless commit
381

382
        tree = Tree.new commit.tree, user_project, ref, params[:filepath]
383
        not_found! "File" unless tree.try(:tree)
384

Saito's avatar
Saito committed
385
        content_type tree.mime_type
386 387 388
        present tree.data
      end

389 390 391
    end
  end
end