Skip to content

Commit

Permalink
Fix group and project search for anonymous users
Browse files Browse the repository at this point in the history
  • Loading branch information
Nick Thomas committed Aug 24, 2017
1 parent 502d646 commit 0614728
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 15 deletions.
15 changes: 10 additions & 5 deletions app/assets/javascripts/api.js
Expand Up @@ -55,13 +55,18 @@ const Api = {
// Return projects list. Filtered by query
projects(query, options, callback) {
const url = Api.buildUrl(Api.projectsPath);
const defaults = {
search: query,
per_page: 20,
};

if (gon.current_user_id) {
defaults.membership = true;
}

return $.ajax({
url,
data: Object.assign({
search: query,
per_page: 20,
membership: true,
}, options),
data: Object.assign(defaults, options),
dataType: 'json',
})
.done(projects => callback(projects));
Expand Down
2 changes: 1 addition & 1 deletion app/views/search/_form.html.haml
Expand Up @@ -11,5 +11,5 @@
%span.sr-only
Clear search
- unless params[:snippets].eql? 'true'
= render 'filter' if current_user
= render 'filter'
= button_tag "Search", class: "btn btn-success btn-search"
@@ -0,0 +1,5 @@
---
title: Fix group and project search for anonymous users
merge_request: 13745
author:
type: fixed
9 changes: 6 additions & 3 deletions doc/api/groups.md
Expand Up @@ -2,7 +2,8 @@

## List groups

Get a list of groups. (As user: my groups or all available, as admin: all groups).
Get a list of visible groups for the authenticated user. When accessed without
authentication, only public groups are returned.

Parameters:

Expand Down Expand Up @@ -43,7 +44,8 @@ You can search for groups by name or path, see below.

## List a group's projects

Get a list of projects in this group.
Get a list of projects in this group. When accessed without authentication, only
public projects are returned.

```
GET /groups/:id/projects
Expand Down Expand Up @@ -109,7 +111,8 @@ Example response:

## Details of a group

Get all details of a group.
Get all details of a group. This endpoint can be accessed without authentication
if the group is publicly accessible.

```
GET /groups/:id
Expand Down
26 changes: 26 additions & 0 deletions spec/features/search_spec.rb
Expand Up @@ -281,4 +281,30 @@
expect(page).to have_selector('.commit-row-description', count: 9)
end
end

context 'anonymous user' do
let(:project) { create(:project, :public) }

before do
sign_out(user)
end

it 'preserves the group being searched in' do
visit search_path(group_id: project.namespace.id)

fill_in 'search', with: 'foo'
click_button 'Search'

expect(find('#group_id').value).to eq(project.namespace.id.to_s)
end

it 'preserves the project being searched in' do
visit search_path(project_id: project.id)

fill_in 'search', with: 'foo'
click_button 'Search'

expect(find('#project_id').value).to eq(project.id.to_s)
end
end
end
26 changes: 24 additions & 2 deletions spec/javascripts/api_spec.js
Expand Up @@ -17,7 +17,7 @@ describe('Api', () => {

beforeEach(() => {
originalGon = window.gon;
window.gon = dummyGon;
window.gon = Object.assign({}, dummyGon);
});

afterEach(() => {
Expand Down Expand Up @@ -98,10 +98,11 @@ describe('Api', () => {
});

describe('projects', () => {
it('fetches projects', (done) => {
it('fetches projects with membership when logged in', (done) => {
const query = 'dummy query';
const options = { unused: 'option' };
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects.json?simple=true`;
window.gon.current_user_id = 1;
const expectedData = Object.assign({
search: query,
per_page: 20,
Expand All @@ -119,6 +120,27 @@ describe('Api', () => {
done();
});
});

it('fetches projects without membership when not logged in', (done) => {
const query = 'dummy query';
const options = { unused: 'option' };
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects.json?simple=true`;
const expectedData = Object.assign({
search: query,
per_page: 20,
}, options);
spyOn(jQuery, 'ajax').and.callFake((request) => {
expect(request.url).toEqual(expectedUrl);
expect(request.dataType).toEqual('json');
expect(request.data).toEqual(expectedData);
return sendDummyResponse();
});

Api.projects(query, options, (response) => {
expect(response).toBe(dummyResponse);
done();
});
});
});

describe('newLabel', () => {
Expand Down
6 changes: 4 additions & 2 deletions spec/javascripts/project_title_spec.js
Expand Up @@ -7,14 +7,15 @@ import '~/project_select';
import '~/project';

describe('Project Title', () => {
const dummyApiVersion = 'v3000';
preloadFixtures('issues/open-issue.html.raw');
loadJSONFixtures('projects.json');

beforeEach(() => {
loadFixtures('issues/open-issue.html.raw');

window.gon = {};
window.gon.api_version = 'v3';
window.gon.api_version = dummyApiVersion;

// eslint-disable-next-line no-new
new Project();
Expand All @@ -37,9 +38,10 @@ describe('Project Title', () => {

it('toggles dropdown', () => {
const $menu = $('.js-dropdown-menu-projects');
window.gon.current_user_id = 1;
$('.js-projects-dropdown-toggle').click();
expect($menu).toHaveClass('open');
expect(reqUrl).toBe('/api/v3/projects.json?simple=true');
expect(reqUrl).toBe(`/api/${dummyApiVersion}/projects.json?simple=true`);
expect(reqData).toEqual({
search: '',
order_by: 'last_activity_at',
Expand Down
21 changes: 19 additions & 2 deletions spec/requests/api/groups_spec.rb
Expand Up @@ -20,10 +20,15 @@

describe "GET /groups" do
context "when unauthenticated" do
it "returns authentication error" do
it "returns public groups" do
get api("/groups")

expect(response).to have_http_status(401)
expect(response).to have_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.length).to eq(1)
expect(json_response)
.to satisfy_one { |group| group['name'] == group1.name }
end
end

Expand Down Expand Up @@ -165,6 +170,18 @@
end

describe "GET /groups/:id" do
context 'when unauthenticated' do
it 'returns 404 for a private group' do
get api("/groups/#{group2.id}")
expect(response).to have_http_status(404)
end

it 'returns 200 for a public group' do
get api("/groups/#{group1.id}")
expect(response).to have_http_status(200)
end
end

context "when authenticated as user" do
it "returns one of user1's groups" do
project = create(:project, namespace: group2, path: 'Foo')
Expand Down

0 comments on commit 0614728

Please sign in to comment.