diff --git a/Guardfile b/Guardfile index 50a10af9..e682f0b6 100644 --- a/Guardfile +++ b/Guardfile @@ -4,6 +4,7 @@ guard 'rspec', :version => 2, :all_on_start => false, :all_after_pass => false do watch(%r{^spec/.+_spec\.rb$}) watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } + watch(%r{^lib/api/(.+)\.rb$}) { |m| "spec/requests/api/#{m[1]}_spec.rb" } watch('spec/spec_helper.rb') { "spec" } # Rails example diff --git a/app/views/help/api.html.haml b/app/views/help/api.html.haml index b1916110..1f0ce879 100644 --- a/app/views/help/api.html.haml +++ b/app/views/help/api.html.haml @@ -1,89 +1,96 @@ -%h3 API +%h3.page_title API .back_link = link_to help_path do ← to index -%hr - -%ol - %li - %a{href: "#README"} README - %li - %a{href: "#projects"} Projects - %li - %a{href: "#snippets"} Snippets - %li - %a{href: "#users"} Users - %li - %a{href: "#session"} Session - %li - %a{href: "#issues"} Issues - %li - %a{href: "#milestones"} Milestones - -.file_holder#README - .file_title - %i.icon-file - README - .file_content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "api", "README.md")) - %br -.file_holder#projects - .file_title - %i.icon-file - Projects - .file_content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "api", "projects.md")) +%ul.nav.nav-tabs.log-tabs + %li.active + = link_to "README", "#README", 'data-toggle' => 'tab' + %li + = link_to "Projects", "#projects", 'data-toggle' => 'tab' + %li + = link_to "Snippets", "#snippets", 'data-toggle' => 'tab' + %li + = link_to "Users", "#users", 'data-toggle' => 'tab' + %li + = link_to "Session", "#session", 'data-toggle' => 'tab' + %li + = link_to "Issues", "#issues", 'data-toggle' => 'tab' + %li + = link_to "Milestones", "#milestones", 'data-toggle' => 'tab' + %li + = link_to "Commits", "#commits", 'data-toggle' => 'tab' -%br +.tab-content + .tab-pane.active#README + .file_holder + .file_title + %i.icon-file + README + .file_content.wiki + = preserve do + = markdown File.read(Rails.root.join("doc", "api", "README.md")) -.file_holder#snippets - .file_title - %i.icon-file - Projects Snippets - .file_content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "api", "snippets.md")) + .tab-pane#projects + .file_holder + .file_title + %i.icon-file + Projects + .file_content.wiki + = preserve do + = markdown File.read(Rails.root.join("doc", "api", "projects.md")) -%br + .tab-pane#snippets + .file_holder + .file_title + %i.icon-file + Projects Snippets + .file_content.wiki + = preserve do + = markdown File.read(Rails.root.join("doc", "api", "snippets.md")) -.file_holder#users - .file_title - %i.icon-file - Users - .file_content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "api", "users.md")) + .tab-pane#users + .file_holder + .file_title + %i.icon-file + Users + .file_content.wiki + = preserve do + = markdown File.read(Rails.root.join("doc", "api", "users.md")) -%br + .tab-pane#session + .file_holder + .file_title + %i.icon-file + Session + .file_content.wiki + = preserve do + = markdown File.read(Rails.root.join("doc", "api", "session.md")) -.file_holder#session - .file_title - %i.icon-file - Session - .file_content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "api", "session.md")) + .tab-pane#issues + .file_holder + .file_title + %i.icon-file + Issues + .file_content.wiki + = preserve do + = markdown File.read(Rails.root.join("doc", "api", "issues.md")) -%br + .tab-pane#milestones + .file_holder + .file_title + %i.icon-file + Milestones + .file_content.wiki + = preserve do + = markdown File.read(Rails.root.join("doc", "api", "milestones.md")) -.file_holder#issues - .file_title - %i.icon-file - Issues - .file_content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "api", "issues.md")) - -%br - -.file_holder#milestones - .file_title - %i.icon-file - Milestones - .file_content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "api", "milestones.md")) + .tab-pane#commits + .file_holder + .file_title + %i.icon-file + Commits + .file_content.wiki + = preserve do + = markdown File.read(Rails.root.join("doc", "api", "commits.md")) diff --git a/doc/api/commits.md b/doc/api/commits.md new file mode 100644 index 00000000..fccb35c3 --- /dev/null +++ b/doc/api/commits.md @@ -0,0 +1,38 @@ +## List Commits + +Get a list of project commits. + +``` +GET /projects/:id/commits +``` + +Parameters: + ++ `id` (required) - The ID or code name of a project ++ `ref_name` (optional) - branch/tag name ++ `page` (optional) ++ `per_page` (optional) + + +```json + +[ + { + "id": "ed899a2f4b50b4370feeea94676502b42383c746", + "short_id": "ed899a2f4b5", + "title": "Replace sanitize with escape once", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dzaporozhets@sphereconsultinginc.com", + "created_at": "2012-09-20T11:50:22+03:00" + }, + { + "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", + "short_id": "6104942438c", + "title": "Sanitize for network graph", + "author_name": "randx", + "author_email": "dmitriy.zaporozhets@gmail.com", + "created_at": "2012-09-20T09:06:12+03:00" + } +] + +``` diff --git a/lib/api.rb b/lib/api.rb index 3b62f31b..f4e9e5fc 100644 --- a/lib/api.rb +++ b/lib/api.rb @@ -19,5 +19,6 @@ module Gitlab mount Milestones mount Keys mount Session + mount Commits end end diff --git a/lib/api/commits.rb b/lib/api/commits.rb new file mode 100644 index 00000000..47d96fc4 --- /dev/null +++ b/lib/api/commits.rb @@ -0,0 +1,29 @@ +module Gitlab + # Commits API + class Commits < Grape::API + before { authenticate! } + + resource :projects do + # Get a list of project commits + # + # Parameters: + # id (required) - The ID or code name of a project + # ref_name (optional) - Name of branch or tag + # page (optional) - default is 0 + # per_page (optional) - default is 20 + # Example Request: + # GET /projects/:id/commits + get ":id/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::Commit + end + end + end +end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index a8b786ae..1909a016 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -17,6 +17,11 @@ module Gitlab expose :id, :url end + class Commit < Grape::Entity + expose :id, :short_id, :title, + :author_name, :author_email, :created_at + end + class Project < Grape::Entity expose :id, :code, :name, :description, :path, :default_branch expose :owner, using: Entities::UserBasic diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 9a08b995..14390545 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -61,7 +61,7 @@ module Gitlab error!({'message' => message}, status) end - private + private def abilities @abilities ||= begin diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb index daaff940..f55dfd04 100644 --- a/lib/api/milestones.rb +++ b/lib/api/milestones.rb @@ -11,6 +11,8 @@ module Gitlab # Example Request: # GET /projects/:id/milestones get ":id/milestones" do + authorize! :read_milestone, user_project + present paginate(user_project.milestones), with: Entities::Milestone end @@ -22,6 +24,8 @@ module Gitlab # Example Request: # GET /projects/:id/milestones/:milestone_id get ":id/milestones/:milestone_id" do + authorize! :read_milestone, user_project + @milestone = user_project.milestones.find(params[:milestone_id]) present @milestone, with: Entities::Milestone end @@ -36,6 +40,8 @@ module Gitlab # Example Request: # POST /projects/:id/milestones post ":id/milestones" do + authorize! :admin_milestone, user_project + attrs = attributes_for_keys [:title, :description, :due_date] @milestone = user_project.milestones.new attrs if @milestone.save diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 1d9004f8..d6ff02c3 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -40,14 +40,14 @@ module Gitlab post do params[:code] ||= params[:name] params[:path] ||= params[:name] - attrs = attributes_for_keys [:code, - :path, - :name, - :description, - :default_branch, - :issues_enabled, - :wall_enabled, - :merge_requests_enabled, + attrs = attributes_for_keys [:code, + :path, + :name, + :description, + :default_branch, + :issues_enabled, + :wall_enabled, + :merge_requests_enabled, :wiki_enabled] @project = Project.create_by_user(attrs, current_user) if @project.saved? @@ -207,6 +207,8 @@ module Gitlab # Example Request: # POST /projects/:id/snippets post ":id/snippets" do + authorize! :write_snippet, user_project + attrs = attributes_for_keys [:title, :file_name] attrs[:expires_at] = params[:lifetime] if params[:lifetime].present? attrs[:content] = params[:code] if params[:code].present? @@ -282,6 +284,8 @@ module Gitlab # Example Request: # GET /projects/:id/repository/commits/:sha/blob get ":id/repository/commits/:sha/blob" do + authorize! :download_code, user_project + ref = params[:sha] commit = user_project.commit ref diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb new file mode 100644 index 00000000..3af5ec21 --- /dev/null +++ b/spec/requests/api/commits_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe Gitlab::API do + include ApiHelpers + + let(:user) { Factory :user } + let!(:project) { Factory :project, owner: user } + + describe "GET /projects/:id/commits" do + context "authorized user" do + before { project.add_access(user, :read) } + + it "should return project commits" do + get api("/projects/#{project.code}/commits", user) + response.status.should == 200 + + json_response.should be_an Array + json_response.first['id'].should == project.commit.id + end + end + + context "unauthorized user" do + it "should return project commits" do + get api("/projects/#{project.code}/commits") + response.status.should == 401 + end + end + end +end