diff --git a/app/controllers/groups/shared_projects_controller.rb b/app/controllers/groups/shared_projects_controller.rb new file mode 100644 index 00000000000..34ba32ce95b --- /dev/null +++ b/app/controllers/groups/shared_projects_controller.rb @@ -0,0 +1,31 @@ +module Groups + class SharedProjectsController < Groups::ApplicationController + respond_to :json + before_action :group + skip_cross_project_access_check :index + + def index + shared_projects = GroupProjectsFinder.new( + group: group, + current_user: current_user, + params: finder_params, + options: { only_shared: true } + ).execute + serializer = GroupChildSerializer.new(current_user: current_user) + .with_pagination(request, response) + + render json: serializer.represent(shared_projects) + end + + private + + def finder_params + @finder_params ||= begin + # Make the `search` param consitent for the frontend, + # which will be using `filter`. + params[:search] ||= params[:filter] if params[:filter] + params.permit(:sort, :search) + end + end + end +end diff --git a/config/routes/group.rb b/config/routes/group.rb index 7c4c3d370e0..fff0914c3cd 100644 --- a/config/routes/group.rb +++ b/config/routes/group.rb @@ -30,6 +30,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do resource :variables, only: [:show, :update] resources :children, only: [:index] + resources :shared_projects, only: [:index] resources :labels, except: [:show] do post :toggle_subscription, on: :member diff --git a/spec/controllers/groups/shared_projects_controller_spec.rb b/spec/controllers/groups/shared_projects_controller_spec.rb new file mode 100644 index 00000000000..f8d1c13416d --- /dev/null +++ b/spec/controllers/groups/shared_projects_controller_spec.rb @@ -0,0 +1,59 @@ +require 'spec_helper' + +describe Groups::SharedProjectsController do + def get_shared_projects(params = {}) + get :index, params.reverse_merge(format: :json, group_id: group.full_path) + end + + def share_project(project) + Projects::GroupLinks::CreateService.new( + project, + user, + link_group_access: ProjectGroupLink::DEVELOPER + ).execute(group) + end + + let(:group) { create(:group) } + let(:user) { create(:user) } + let!(:shared_project) do + shared_project = create(:project, namespace: user.namespace) + share_project(shared_project) + + shared_project + end + + let(:json_project_ids) { json_response.map { |project_info| project_info['id'] } } + + before do + sign_in(user) + end + + describe 'GET #index' do + it 'returns only projects shared with the group' do + create(:project, namespace: group) + + get_shared_projects + + expect(json_project_ids).to contain_exactly(shared_project.id) + end + + it 'allows fitlering shared projects' do + project = create(:project, :archived, namespace: user.namespace, name: "Searching for") + share_project(project) + + get_shared_projects(filter: 'search') + + expect(json_project_ids).to contain_exactly(project.id) + end + + it 'allows sorting projects' do + shared_project.update!(name: 'bbb') + second_project = create(:project, namespace: user.namespace, name: 'aaaa') + share_project(second_project) + + get_shared_projects(sort: 'name_asc') + + expect(json_project_ids).to eq([second_project.id, shared_project.id]) + end + end +end