From 8edc6b6a8c240322499356df96e1199bb6bbc872 Mon Sep 17 00:00:00 2001 From: Christian Simon <cs@f03.eu> Date: Tue, 8 Jan 2013 22:05:00 +0100 Subject: [PATCH 1/5] Add api for creating/listing/viewing groups --- lib/api.rb | 3 ++- lib/api/entities.rb | 10 +++++++++ lib/api/groups.rb | 50 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 lib/api/groups.rb diff --git a/lib/api.rb b/lib/api.rb index f58b82ff98e..81a5919f1d3 100644 --- a/lib/api.rb +++ b/lib/api.rb @@ -11,7 +11,8 @@ module Gitlab format :json error_format :json helpers APIHelpers - + + mount Groups mount Users mount Projects mount Issues diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 5cbb1118a89..3bbbd831548 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -32,6 +32,16 @@ module Gitlab end end + class Group < Grape::Entity + expose :id, :name, :path, :name, :owner_id, :type + end + + class GroupDetail < Grape::Entity + expose :id, :name, :path, :name, :owner_id, :type + expose :projects, using: Entities::Project + end + + class RepoObject < Grape::Entity expose :name, :commit expose :protected do |repo, options| diff --git a/lib/api/groups.rb b/lib/api/groups.rb new file mode 100644 index 00000000000..bc856eccdab --- /dev/null +++ b/lib/api/groups.rb @@ -0,0 +1,50 @@ +module Gitlab + # groups API + class Groups < Grape::API + before { authenticate! } + + resource :groups do + # Get a groups list + # + # Example Request: + # GET /groups + get do + @groups = paginate Group + present @groups, with: Entities::Group + + end + + # Create group. Available only for admin + # + # Parameters: + # name (required) - Name + # path (required) - Path + # Example Request: + # POST /groups + post do + authenticated_as_admin! + attrs = attributes_for_keys [:name, :path] + @group = Group.new(attrs) + @group.owner = current_user + + if @group.save + present @group, with: Entities::Group + else + not_found! + end + end + + # Get a single group, with containing projects + # + # Parameters: + # id (required) - The ID of a group + # Example Request: + # GET /groups/:id + get ":id" do + @group = Group.find(params[:id]) + present @group, with: Entities::GroupDetail + end + + end + end +end -- GitLab From fc0c69287069af9a47176abb1488f653f91eebdb Mon Sep 17 00:00:00 2001 From: Christian Simon <cs@f03.eu> Date: Fri, 1 Feb 2013 14:59:22 +0100 Subject: [PATCH 2/5] Add docs/tests for groups api --- doc/api/README.md | 1 + doc/api/groups.md | 45 ++++++++++++++++ spec/requests/api/groups_spec.rb | 88 ++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 doc/api/groups.md create mode 100644 spec/requests/api/groups_spec.rb diff --git a/doc/api/README.md b/doc/api/README.md index 65eec6bec3c..0618db7e369 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -32,6 +32,7 @@ When listing resources you can pass the following parameters: + [Users](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/users.md) + [Session](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/session.md) + [Projects](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/projects.md) ++ [Groups](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/groups.md) + [Snippets](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/snippets.md) + [Repositories](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/repositories.md) + [Issues](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/issues.md) diff --git a/doc/api/groups.md b/doc/api/groups.md new file mode 100644 index 00000000000..00a7387c76f --- /dev/null +++ b/doc/api/groups.md @@ -0,0 +1,45 @@ +## List project groups + +Get a list of groups. (As user: my groups, as admin: all groups) + +``` +GET /groups +``` + +```json +[ + { + "id": 1, + "name": "Foobar Group", + "path": "foo-bar", + "owner_id": 18 + } +] +``` + +## Details of group + +Get all details of a group. + +``` +GET /groups/:id +``` + +Parameters: + ++ `id` (required) - The ID of a group + +## New group + +Create a new project group. Available only for admin + +``` +POST /groups +``` + +Parameters: ++ `name` (required) - Email ++ `path` - Password + +Will return created group with status `201 Created` on success, or `404 Not found` on fail. + diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb new file mode 100644 index 00000000000..c9980db9ad6 --- /dev/null +++ b/spec/requests/api/groups_spec.rb @@ -0,0 +1,88 @@ +require 'spec_helper' + +describe Gitlab::API do + include ApiHelpers + + let(:user1) { create(:user) } + let(:user2) { create(:user) } + let(:admin) { create(:admin) } + let!(:group1) { create(:group, owner: user1) } + let!(:group2) { create(:group, owner: user2) } + + describe "GET /groups" do + context "when unauthenticated" do + it "should return authentication error" do + get api("/groups") + response.status.should == 401 + end + end + + context "when authenticated as user" do + it "normal user: should return an array of groups of user1" do + get api("/groups", user1) + response.status.should == 200 + json_response.should be_an Array + json_response.length.should == 1 + json_response.first['name'].should == group1.name + end + end + + context "when authenticated as admin" do + it "admin: should return an array of all groups" do + get api("/groups", admin) + response.status.should == 200 + json_response.should be_an Array + json_response.length.should == 2 + end + end + end + + describe "GET /groups/:id" do + context "when authenticated as user" do + it "should return one of user1's groups" do + get api("/groups/#{group1.id}", user1) + response.status.should == 200 + json_response['name'] == group1.name + end + + it "should not return a non existing group" do + get api("/groups/1328", user1) + response.status.should == 404 + end + + it "should not return a group not attached to user1" do + get api("/groups/#{group2.id}", user1) + response.status.should == 404 + end + end + + context "when authenticated as admin" do + it "should return any existing group" do + get api("/groups/#{group2.id}", admin) + response.status.should == 200 + json_response['name'] == group2.name + end + + it "should not return a non existing group" do + get api("/groups/1328", admin) + response.status.should == 404 + end + end + end + + describe "POST /groups" do + context "when authenticated as user" do + it "should not create group" do + post api("/groups", user1), attributes_for(:group) + response.status.should == 403 + end + end + + context "when authenticated as admin" do + it "should create group" do + post api("/groups", admin), attributes_for(:group) + response.status.should == 201 + end + end + end +end -- GitLab From 149ccd5d91abf0c4b7ec610c03ad46a8ad17eec2 Mon Sep 17 00:00:00 2001 From: Christian Simon <cs@f03.eu> Date: Fri, 1 Feb 2013 15:00:12 +0100 Subject: [PATCH 3/5] Fix groups api: differ between users and admin --- lib/api/entities.rb | 2 +- lib/api/groups.rb | 92 ++++++++++++++++++++++++--------------------- 2 files changed, 50 insertions(+), 44 deletions(-) diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 3bbbd831548..b78fc1b86fe 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -33,7 +33,7 @@ module Gitlab end class Group < Grape::Entity - expose :id, :name, :path, :name, :owner_id, :type + expose :id, :name, :path, :owner_id end class GroupDetail < Grape::Entity diff --git a/lib/api/groups.rb b/lib/api/groups.rb index bc856eccdab..a67caef0bc5 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -2,49 +2,55 @@ module Gitlab # groups API class Groups < Grape::API before { authenticate! } - - resource :groups do - # Get a groups list - # - # Example Request: - # GET /groups - get do - @groups = paginate Group - present @groups, with: Entities::Group - end - - # Create group. Available only for admin - # - # Parameters: - # name (required) - Name - # path (required) - Path - # Example Request: - # POST /groups - post do - authenticated_as_admin! - attrs = attributes_for_keys [:name, :path] - @group = Group.new(attrs) - @group.owner = current_user - - if @group.save - present @group, with: Entities::Group - else - not_found! - end - end - - # Get a single group, with containing projects - # - # Parameters: - # id (required) - The ID of a group - # Example Request: - # GET /groups/:id - get ":id" do - @group = Group.find(params[:id]) - present @group, with: Entities::GroupDetail - end - - end + resource :groups do + # Get a groups list + # + # Example Request: + # GET /groups + get do + if current_user.admin + @groups = paginate Group + else + @groups = paginate current_user.groups + end + present @groups, with: Entities::Group + end + + # Create group. Available only for admin + # + # Parameters: + # name (required) - Name + # path (required) - Path + # Example Request: + # POST /groups + post do + authenticated_as_admin! + attrs = attributes_for_keys [:name, :path] + @group = Group.new(attrs) + @group.owner = current_user + + if @group.save + present @group, with: Entities::Group + else + not_found! + end + end + + # Get a single group, with containing projects + # + # Parameters: + # id (required) - The ID of a group + # Example Request: + # GET /groups/:id + get ":id" do + @group = Group.find(params[:id]) + if current_user.admin or current_user.groups.include? @group + present @group, with: Entities::GroupDetail + else + not_found! + end + end + end end end -- GitLab From 6dba727cb282ee19b5e4c6b0d0e3ec3bff01ac63 Mon Sep 17 00:00:00 2001 From: Christian Simon <cs@f03.eu> Date: Fri, 1 Feb 2013 18:58:53 +0100 Subject: [PATCH 4/5] Add test for duplicate group paths --- spec/requests/api/groups_spec.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index c9980db9ad6..c39a4228408 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -83,6 +83,11 @@ describe Gitlab::API do post api("/groups", admin), attributes_for(:group) response.status.should == 201 end + + it "should not create group, duplicate" do + post api("/groups", admin), {:name => "Duplicate Test", :path => group2.path} + response.status.should == 404 + end end end end -- GitLab From 33c48ecd35f4a2d5b2596882e36e722f700aff2f Mon Sep 17 00:00:00 2001 From: Christian Simon <cs@f03.eu> Date: Sun, 3 Feb 2013 19:38:33 +0100 Subject: [PATCH 5/5] Code deduplication using inheritance for GroupDetail --- lib/api/entities.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/api/entities.rb b/lib/api/entities.rb index b78fc1b86fe..c1873d87b55 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -36,8 +36,7 @@ module Gitlab expose :id, :name, :path, :owner_id end - class GroupDetail < Grape::Entity - expose :id, :name, :path, :name, :owner_id, :type + class GroupDetail < Group expose :projects, using: Entities::Project end -- GitLab