Commit 318350e34fcd0b0754526fdfb94c484b8bb88837
Exists in
master
and in
4 other branches
Merge branch 'api' of https://github.com/NARKOZ/gitlabhq
Conflicts: Gemfile.lock
Showing
9 changed files
with
206 additions
and
0 deletions
Show diff stats
Gemfile
@@ -18,6 +18,7 @@ gem 'yaml_db', :git => "https://github.com/gitlabhq/yaml_db.git" | @@ -18,6 +18,7 @@ gem 'yaml_db', :git => "https://github.com/gitlabhq/yaml_db.git" | ||
18 | gem 'grack', :git => "https://github.com/gitlabhq/grack.git" | 18 | gem 'grack', :git => "https://github.com/gitlabhq/grack.git" |
19 | gem "linguist", "~> 1.0.0", :git => "https://github.com/gitlabhq/linguist.git" | 19 | gem "linguist", "~> 1.0.0", :git => "https://github.com/gitlabhq/linguist.git" |
20 | 20 | ||
21 | +gem "grape" | ||
21 | gem "stamp" | 22 | gem "stamp" |
22 | gem "kaminari" | 23 | gem "kaminari" |
23 | gem "haml-rails" | 24 | gem "haml-rails" |
Gemfile.lock
@@ -169,6 +169,12 @@ GEM | @@ -169,6 +169,12 @@ GEM | ||
169 | gherkin (2.11.0) | 169 | gherkin (2.11.0) |
170 | json (>= 1.4.6) | 170 | json (>= 1.4.6) |
171 | git (1.2.5) | 171 | git (1.2.5) |
172 | + grape (0.2.0) | ||
173 | + hashie (~> 1.2) | ||
174 | + multi_json | ||
175 | + multi_xml | ||
176 | + rack | ||
177 | + rack-mount | ||
172 | haml (3.1.6) | 178 | haml (3.1.6) |
173 | haml-rails (0.3.4) | 179 | haml-rails (0.3.4) |
174 | actionpack (~> 3.0) | 180 | actionpack (~> 3.0) |
@@ -230,6 +236,8 @@ GEM | @@ -230,6 +236,8 @@ GEM | ||
230 | rack (1.4.1) | 236 | rack (1.4.1) |
231 | rack-cache (1.2) | 237 | rack-cache (1.2) |
232 | rack (>= 0.4) | 238 | rack (>= 0.4) |
239 | + rack-mount (0.8.3) | ||
240 | + rack (>= 1.0.0) | ||
233 | rack-protection (1.2.0) | 241 | rack-protection (1.2.0) |
234 | rack | 242 | rack |
235 | rack-ssl (1.3.2) | 243 | rack-ssl (1.3.2) |
@@ -381,6 +389,7 @@ DEPENDENCIES | @@ -381,6 +389,7 @@ DEPENDENCIES | ||
381 | git | 389 | git |
382 | gitolite! | 390 | gitolite! |
383 | grack! | 391 | grack! |
392 | + grape | ||
384 | grit! | 393 | grit! |
385 | haml-rails | 394 | haml-rails |
386 | httparty | 395 | httparty |
config/routes.rb
@@ -4,6 +4,10 @@ Gitlab::Application.routes.draw do | @@ -4,6 +4,10 @@ Gitlab::Application.routes.draw do | ||
4 | # | 4 | # |
5 | get 'search' => "search#show" | 5 | get 'search' => "search#show" |
6 | 6 | ||
7 | + # API | ||
8 | + require 'api' | ||
9 | + mount Gitlab::API => '/api' | ||
10 | + | ||
7 | # Optionally, enable Resque here | 11 | # Optionally, enable Resque here |
8 | require 'resque/server' | 12 | require 'resque/server' |
9 | mount Resque::Server.new, at: '/info/resque' | 13 | mount Resque::Server.new, at: '/info/resque' |
@@ -0,0 +1,61 @@ | @@ -0,0 +1,61 @@ | ||
1 | +require 'api/entities' | ||
2 | +require 'api/helpers' | ||
3 | + | ||
4 | +module Gitlab | ||
5 | + class API < Grape::API | ||
6 | + format :json | ||
7 | + helpers APIHelpers | ||
8 | + | ||
9 | + # Users API | ||
10 | + resource :users do | ||
11 | + before { authenticate! } | ||
12 | + | ||
13 | + # GET /users | ||
14 | + get do | ||
15 | + @users = User.all | ||
16 | + present @users, :with => Entities::User | ||
17 | + end | ||
18 | + | ||
19 | + # GET /users/:id | ||
20 | + get ":id" do | ||
21 | + @user = User.find(params[:id]) | ||
22 | + present @user, :with => Entities::User | ||
23 | + end | ||
24 | + end | ||
25 | + | ||
26 | + # GET /user | ||
27 | + get "/user" do | ||
28 | + authenticate! | ||
29 | + present @current_user, :with => Entities::User | ||
30 | + end | ||
31 | + | ||
32 | + # Projects API | ||
33 | + resource :projects do | ||
34 | + before { authenticate! } | ||
35 | + | ||
36 | + # GET /projects | ||
37 | + get do | ||
38 | + @projects = current_user.projects | ||
39 | + present @projects, :with => Entities::Project | ||
40 | + end | ||
41 | + | ||
42 | + # GET /projects/:id | ||
43 | + get ":id" do | ||
44 | + @project = current_user.projects.find_by_code(params[:id]) | ||
45 | + present @project, :with => Entities::Project | ||
46 | + end | ||
47 | + | ||
48 | + # GET /projects/:id/repository/branches | ||
49 | + get ":id/repository/branches" do | ||
50 | + @project = current_user.projects.find_by_code(params[:id]) | ||
51 | + present @project.repo.heads.sort_by(&:name), :with => Entities::ProjectRepositoryBranches | ||
52 | + end | ||
53 | + | ||
54 | + # GET /projects/:id/repository/tags | ||
55 | + get ":id/repository/tags" do | ||
56 | + @project = current_user.projects.find_by_code(params[:id]) | ||
57 | + present @project.repo.tags.sort_by(&:name).reverse, :with => Entities::ProjectRepositoryTags | ||
58 | + end | ||
59 | + end | ||
60 | + end | ||
61 | +end |
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +module Gitlab | ||
2 | + module Entities | ||
3 | + class User < Grape::Entity | ||
4 | + expose :id, :email, :name, :bio, :skype, :linkedin, :twitter, | ||
5 | + :dark_scheme, :theme_id, :blocked, :created_at | ||
6 | + end | ||
7 | + | ||
8 | + class Project < Grape::Entity | ||
9 | + expose :id, :code, :name, :description, :path, :default_branch | ||
10 | + expose :owner, :using => Entities::User | ||
11 | + expose :private_flag, :as => :private | ||
12 | + expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :created_at | ||
13 | + end | ||
14 | + | ||
15 | + class ProjectRepositoryBranches < Grape::Entity | ||
16 | + expose :name, :commit | ||
17 | + end | ||
18 | + | ||
19 | + class ProjectRepositoryTags < Grape::Entity | ||
20 | + expose :name, :commit | ||
21 | + end | ||
22 | + end | ||
23 | +end |
@@ -0,0 +1,55 @@ | @@ -0,0 +1,55 @@ | ||
1 | +require 'spec_helper' | ||
2 | + | ||
3 | +describe Gitlab::API do | ||
4 | + let(:user) { Factory :user } | ||
5 | + let!(:project) { Factory :project, :owner => user } | ||
6 | + before { project.add_access(user, :read) } | ||
7 | + | ||
8 | + describe "GET /projects" do | ||
9 | + it "should return authentication error" do | ||
10 | + get "/api/projects" | ||
11 | + response.status.should == 401 | ||
12 | + end | ||
13 | + | ||
14 | + describe "authenticated GET /projects" do | ||
15 | + it "should return an array of projects" do | ||
16 | + get "/api/projects?private_token=#{user.private_token}" | ||
17 | + response.status.should == 200 | ||
18 | + json = JSON.parse(response.body) | ||
19 | + json.should be_an Array | ||
20 | + json.first['name'].should == project.name | ||
21 | + json.first['owner']['email'].should == user.email | ||
22 | + end | ||
23 | + end | ||
24 | + end | ||
25 | + | ||
26 | + describe "GET /projects/:id" do | ||
27 | + it "should return a project by id" do | ||
28 | + get "/api/projects/#{project.code}?private_token=#{user.private_token}" | ||
29 | + response.status.should == 200 | ||
30 | + json = JSON.parse(response.body) | ||
31 | + json['name'].should == project.name | ||
32 | + json['owner']['email'].should == user.email | ||
33 | + end | ||
34 | + end | ||
35 | + | ||
36 | + describe "GET /projects/:id/repository/branches" do | ||
37 | + it "should return an array of project branches" do | ||
38 | + get "/api/projects/#{project.code}/repository/branches?private_token=#{user.private_token}" | ||
39 | + response.status.should == 200 | ||
40 | + json = JSON.parse(response.body) | ||
41 | + json.should be_an Array | ||
42 | + json.first['name'].should == project.repo.heads.sort_by(&:name).first.name | ||
43 | + end | ||
44 | + end | ||
45 | + | ||
46 | + describe "GET /projects/:id/repository/tags" do | ||
47 | + it "should return an array of project tags" do | ||
48 | + get "/api/projects/#{project.code}/repository/tags?private_token=#{user.private_token}" | ||
49 | + response.status.should == 200 | ||
50 | + json = JSON.parse(response.body) | ||
51 | + json.should be_an Array | ||
52 | + json.first['name'].should == project.repo.tags.sort_by(&:name).reverse.first.name | ||
53 | + end | ||
54 | + end | ||
55 | +end |
@@ -0,0 +1,38 @@ | @@ -0,0 +1,38 @@ | ||
1 | +require 'spec_helper' | ||
2 | + | ||
3 | +describe Gitlab::API do | ||
4 | + let(:user) { Factory :user } | ||
5 | + | ||
6 | + describe "GET /users" do | ||
7 | + it "should return authentication error" do | ||
8 | + get "/api/users" | ||
9 | + response.status.should == 401 | ||
10 | + end | ||
11 | + | ||
12 | + describe "authenticated GET /users" do | ||
13 | + it "should return an array of users" do | ||
14 | + get "/api/users?private_token=#{user.private_token}" | ||
15 | + response.status.should == 200 | ||
16 | + json = JSON.parse(response.body) | ||
17 | + json.should be_an Array | ||
18 | + json.first['email'].should == user.email | ||
19 | + end | ||
20 | + end | ||
21 | + end | ||
22 | + | ||
23 | + describe "GET /users/:id" do | ||
24 | + it "should return a user by id" do | ||
25 | + get "/api/users/#{user.id}?private_token=#{user.private_token}" | ||
26 | + response.status.should == 200 | ||
27 | + JSON.parse(response.body)['email'].should == user.email | ||
28 | + end | ||
29 | + end | ||
30 | + | ||
31 | + describe "GET /user" do | ||
32 | + it "should return current user" do | ||
33 | + get "/api/user?private_token=#{user.private_token}" | ||
34 | + response.status.should == 200 | ||
35 | + JSON.parse(response.body)['email'].should == user.email | ||
36 | + end | ||
37 | + end | ||
38 | +end |
spec/spec_helper.rb
@@ -58,4 +58,8 @@ RSpec.configure do |config| | @@ -58,4 +58,8 @@ RSpec.configure do |config| | ||
58 | config.after do | 58 | config.after do |
59 | DatabaseCleaner.clean | 59 | DatabaseCleaner.clean |
60 | end | 60 | end |
61 | + | ||
62 | + config.include RSpec::Rails::RequestExampleGroup, :type => :request, :example_group => { | ||
63 | + :file_path => /spec\/api/ | ||
64 | + } | ||
61 | end | 65 | end |