Commit 1165759b14b02ad87dff46716e37e569f678b0b5
Exists in
master
and in
4 other branches
Merge pull request #5146 from karlhungus/feature-api-search-for-projects-by-name
Added search for projects by name to api
Showing
4 changed files
with
86 additions
and
20 deletions
Show diff stats
app/contexts/search_context.rb
| @@ -13,7 +13,7 @@ class SearchContext | @@ -13,7 +13,7 @@ class SearchContext | ||
| 13 | projects = Project.where(id: project_ids) | 13 | projects = Project.where(id: project_ids) |
| 14 | result[:projects] = projects.search(query).limit(20) | 14 | result[:projects] = projects.search(query).limit(20) |
| 15 | 15 | ||
| 16 | - # Search inside singe project | 16 | + # Search inside single project |
| 17 | project = projects.first if projects.length == 1 | 17 | project = projects.first if projects.length == 1 |
| 18 | 18 | ||
| 19 | if params[:search_code].present? | 19 | if params[:search_code].present? |
doc/api/projects.md
| @@ -484,3 +484,18 @@ DELETE /projects/:id/fork | @@ -484,3 +484,18 @@ DELETE /projects/:id/fork | ||
| 484 | Parameter: | 484 | Parameter: |
| 485 | 485 | ||
| 486 | + `id` (required) - The ID of the project | 486 | + `id` (required) - The ID of the project |
| 487 | + | ||
| 488 | + | ||
| 489 | +## Search for projects by name | ||
| 490 | + | ||
| 491 | +Search for projects by name which are public or the calling user has access to | ||
| 492 | + | ||
| 493 | +``` | ||
| 494 | +GET /projects/search/:query | ||
| 495 | +``` | ||
| 496 | + | ||
| 497 | +Parameters: | ||
| 498 | + | ||
| 499 | ++ query (required) - A string contained in the project name | ||
| 500 | ++ per_page (optional) - number of projects to return per page | ||
| 501 | ++ page (optional) - the page to retrieve |
lib/api/projects.rb
| @@ -73,16 +73,16 @@ module API | @@ -73,16 +73,16 @@ module API | ||
| 73 | post do | 73 | post do |
| 74 | required_attributes! [:name] | 74 | required_attributes! [:name] |
| 75 | attrs = attributes_for_keys [:name, | 75 | attrs = attributes_for_keys [:name, |
| 76 | - :path, | ||
| 77 | - :description, | ||
| 78 | - :default_branch, | ||
| 79 | - :issues_enabled, | ||
| 80 | - :wall_enabled, | ||
| 81 | - :merge_requests_enabled, | ||
| 82 | - :wiki_enabled, | ||
| 83 | - :snippets_enabled, | ||
| 84 | - :namespace_id, | ||
| 85 | - :public] | 76 | + :path, |
| 77 | + :description, | ||
| 78 | + :default_branch, | ||
| 79 | + :issues_enabled, | ||
| 80 | + :wall_enabled, | ||
| 81 | + :merge_requests_enabled, | ||
| 82 | + :wiki_enabled, | ||
| 83 | + :snippets_enabled, | ||
| 84 | + :namespace_id, | ||
| 85 | + :public] | ||
| 86 | @project = ::Projects::CreateContext.new(current_user, attrs).execute | 86 | @project = ::Projects::CreateContext.new(current_user, attrs).execute |
| 87 | if @project.saved? | 87 | if @project.saved? |
| 88 | present @project, with: Entities::Project | 88 | present @project, with: Entities::Project |
| @@ -113,14 +113,14 @@ module API | @@ -113,14 +113,14 @@ module API | ||
| 113 | authenticated_as_admin! | 113 | authenticated_as_admin! |
| 114 | user = User.find(params[:user_id]) | 114 | user = User.find(params[:user_id]) |
| 115 | attrs = attributes_for_keys [:name, | 115 | attrs = attributes_for_keys [:name, |
| 116 | - :description, | ||
| 117 | - :default_branch, | ||
| 118 | - :issues_enabled, | ||
| 119 | - :wall_enabled, | ||
| 120 | - :merge_requests_enabled, | ||
| 121 | - :wiki_enabled, | ||
| 122 | - :snippets_enabled, | ||
| 123 | - :public] | 116 | + :description, |
| 117 | + :default_branch, | ||
| 118 | + :issues_enabled, | ||
| 119 | + :wall_enabled, | ||
| 120 | + :merge_requests_enabled, | ||
| 121 | + :wiki_enabled, | ||
| 122 | + :snippets_enabled, | ||
| 123 | + :public] | ||
| 124 | @project = ::Projects::CreateContext.new(user, attrs).execute | 124 | @project = ::Projects::CreateContext.new(user, attrs).execute |
| 125 | if @project.saved? | 125 | if @project.saved? |
| 126 | present @project, with: Entities::Project | 126 | present @project, with: Entities::Project |
| @@ -165,7 +165,6 @@ module API | @@ -165,7 +165,6 @@ module API | ||
| 165 | end | 165 | end |
| 166 | end | 166 | end |
| 167 | 167 | ||
| 168 | - | ||
| 169 | # Get a project team members | 168 | # Get a project team members |
| 170 | # | 169 | # |
| 171 | # Parameters: | 170 | # Parameters: |
| @@ -262,6 +261,20 @@ module API | @@ -262,6 +261,20 @@ module API | ||
| 262 | {message: "Access revoked", id: params[:user_id].to_i} | 261 | {message: "Access revoked", id: params[:user_id].to_i} |
| 263 | end | 262 | end |
| 264 | end | 263 | end |
| 264 | + | ||
| 265 | + # search for projects current_user has access to | ||
| 266 | + # | ||
| 267 | + # Parameters: | ||
| 268 | + # query (required) - A string contained in the project name | ||
| 269 | + # per_page (optional) - number of projects to return per page | ||
| 270 | + # page (optional) - the page to retrieve | ||
| 271 | + # Example Request: | ||
| 272 | + # GET /projects/search/:query | ||
| 273 | + get "/search/:query" do | ||
| 274 | + ids = current_user.authorized_projects.map(&:id) | ||
| 275 | + projects = Project.where("(id in (?) OR public = true) AND (name LIKE (?))", ids, "%#{params[:query]}%") | ||
| 276 | + present paginate(projects), with: Entities::Project | ||
| 277 | + end | ||
| 265 | end | 278 | end |
| 266 | end | 279 | end |
| 267 | end | 280 | end |
spec/requests/api/projects_spec.rb
| @@ -692,4 +692,42 @@ describe API::API do | @@ -692,4 +692,42 @@ describe API::API do | ||
| 692 | end | 692 | end |
| 693 | end | 693 | end |
| 694 | end | 694 | end |
| 695 | + | ||
| 696 | + describe "GET /projects/search/:query" do | ||
| 697 | + let!(:query) { 'query'} | ||
| 698 | + let!(:search) { create(:project, name: query, creator_id: user.id, namespace: user.namespace) } | ||
| 699 | + let!(:pre) { create(:project, name: "pre_#{query}", creator_id: user.id, namespace: user.namespace) } | ||
| 700 | + let!(:post) { create(:project, name: "#{query}_post", creator_id: user.id, namespace: user.namespace) } | ||
| 701 | + let!(:pre_post) { create(:project, name: "pre_#{query}_post", creator_id: user.id, namespace: user.namespace) } | ||
| 702 | + let!(:unfound) { create(:project, name: 'unfound', creator_id: user.id, namespace: user.namespace) } | ||
| 703 | + let!(:public) { create(:project, name: "another #{query}",public: true) } | ||
| 704 | + let!(:unfound_public) { create(:project, name: 'unfound public', public: true) } | ||
| 705 | + | ||
| 706 | + context "when unauthenticated" do | ||
| 707 | + it "should return authentication error" do | ||
| 708 | + get api("/projects/search/#{query}") | ||
| 709 | + response.status.should == 401 | ||
| 710 | + end | ||
| 711 | + end | ||
| 712 | + | ||
| 713 | + context "when authenticated" do | ||
| 714 | + it "should return an array of projects" do | ||
| 715 | + get api("/projects/search/#{query}",user) | ||
| 716 | + response.status.should == 200 | ||
| 717 | + json_response.should be_an Array | ||
| 718 | + json_response.size.should == 5 | ||
| 719 | + json_response.each {|project| project['name'].should =~ /.*query.*/} | ||
| 720 | + end | ||
| 721 | + end | ||
| 722 | + | ||
| 723 | + context "when authenticated as a different user" do | ||
| 724 | + it "should return matching public projects" do | ||
| 725 | + get api("/projects/search/#{query}", user2) | ||
| 726 | + response.status.should == 200 | ||
| 727 | + json_response.should be_an Array | ||
| 728 | + json_response.size.should == 1 | ||
| 729 | + json_response.first['name'].should == "another #{query}" | ||
| 730 | + end | ||
| 731 | + end | ||
| 732 | + end | ||
| 695 | end | 733 | end |