diff --git a/CHANGELOG b/CHANGELOG index a964a1922162fb2bbf7a0502f7b8297cf1b133dd..adb1d65c1359781c1caa6431f39b1c88248e3e78 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,18 +1,18 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.13.0 (unreleased) + - Fix user autocomplete for unauthenticated users accessing public projects (Stan Hu) - Fix redirection to home page URL for unauthorized users (Daniel Gerhardt) - Add branch switching support for graphs (Daniel Gerhardt) - Fix external issue tracker hook/test for HTTPS URLs (Daniel Gerhardt) - Remove link leading to a 404 error in Deploy Keys page (Stan Hu) - Add support for unlocking users in admin settings (Stan Hu) - Add Irker service configuration options (Stan Hu) - - Fix order of issues imported form GitHub (Hiroyuki Sato) + - Fix order of issues imported from GitHub (Hiroyuki Sato) - Bump rugments to 1.0.0beta8 to fix C prototype function highlighting (Jonathon Reinhart) - Fix Merge Request webhook to properly fire "merge" action when accepted from the web UI - Add `two_factor_enabled` field to admin user API (Stan Hu) - Fix invalid timestamps in RSS feeds (Rowan Wookey) - - Fix error when deleting a user who has projects (Stan Hu) - Fix downloading of patches on public merge requests when user logged out (Stan Hu) - The password for the default administrator (root) account has been changed from "5iveL!fe" to "password". - Fix Error 500 when relative submodule resolves to a namespace that has a different name from its path (Stan Hu) @@ -43,6 +43,7 @@ v 7.13.0 (unreleased) - Redesign project page. Show README as default instead of activity. Move project activity to separate page - Make left menu more hierarchical and less contextual by adding back item at top - A fork can’t have a visibility level that is greater than the original project. + - Faster code search in repository and wiki. Fixes search page timeout for big repositories v 7.12.2 - Correctly show anonymous authorized applications under Profile > Applications. diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee index a747614601055416fbc21df03d62b8946a883fa1..a4f511301c19bf321751561ab98147263791fb4f 100644 --- a/app/assets/javascripts/dropzone_input.js.coffee +++ b/app/assets/javascripts/dropzone_input.js.coffee @@ -25,10 +25,10 @@ class @DropzoneInput form_dropzone = $(form).find('.div-dropzone') form_dropzone.parent().addClass "div-dropzone-wrapper" form_dropzone.append divHover - $(".div-dropzone-hover").append iconPaperclip + form_dropzone.find(".div-dropzone-hover").append iconPaperclip form_dropzone.append divSpinner - $(".div-dropzone-spinner").append iconSpinner - $(".div-dropzone-spinner").css + form_dropzone.find(".div-dropzone-spinner").append iconSpinner + form_dropzone.find(".div-dropzone-spinner").css "opacity": 0 "display": "none" diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb index 11af9895261f1a683df092e4f03d9dad02a6e0c5..52e9c58b47cab90142bce38519fc53a586ddb7b5 100644 --- a/app/controllers/autocomplete_controller.rb +++ b/app/controllers/autocomplete_controller.rb @@ -1,22 +1,35 @@ class AutocompleteController < ApplicationController + skip_before_action :authenticate_user!, only: [:users] + def users - @users = - if params[:project_id].present? - project = Project.find(params[:project_id]) + begin + @users = + if params[:project_id].present? + project = Project.find(params[:project_id]) - if can?(current_user, :read_project, project) - project.team.users - end - elsif params[:group_id] - group = Group.find(params[:group_id]) + if can?(current_user, :read_project, project) + project.team.users + end + elsif params[:group_id] + group = Group.find(params[:group_id]) - if can?(current_user, :read_group, group) - group.users + if can?(current_user, :read_group, group) + group.users + end + elsif current_user + User.all end - else - User.all + rescue ActiveRecord::RecordNotFound + if current_user + return render json: {}, status: 404 end + end + + if @users.nil? && current_user.nil? + authenticate_user! + end + @users ||= User.none @users = @users.search(params[:search]) if params[:search].present? @users = @users.active @users = @users.page(params[:page]).per(PER_PAGE) diff --git a/app/models/repository.rb b/app/models/repository.rb index c767d1051d12cb0544cf97536937ccd41a4f013e..6262b5c4c92165bacedcf4f81b238eab8216dc42 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -431,6 +431,40 @@ class Repository end end + def search_files(query, ref) + offset = 2 + args = %W(git grep -i -n --before-context #{offset} --after-context #{offset} #{query} #{ref || root_ref}) + Gitlab::Popen.popen(args, path_to_repo).first.scrub.split(/^--$/) + end + + def parse_search_result(result) + ref = nil + filename = nil + startline = 0 + + lines = result.lines + lines.each_with_index do |line, index| + if line =~ /^.*:.*:\d+:/ + ref, filename, startline = line.split(':') + startline = startline.to_i - index + break + end + end + + data = lines.map do |line| + line.sub(ref, '').sub(filename, '').sub(/^:-\d+-/, '').sub(/^::\d+:/, '') + end + + data = data.join("") + + OpenStruct.new( + filename: filename, + ref: ref, + startline: startline, + data: data + ) + end + private def cache diff --git a/app/views/search/results/_blob.html.haml b/app/views/search/results/_blob.html.haml index 84e9be82c444e2596cc2c95472ed282a9e5dd18f..58f58eff54d048db97352ba8b494604c450d89ff 100644 --- a/app/views/search/results/_blob.html.haml +++ b/app/views/search/results/_blob.html.haml @@ -1,3 +1,4 @@ +- blob = @project.repository.parse_search_result(blob) .blob-result .file-holder .file-title diff --git a/app/views/search/results/_wiki_blob.html.haml b/app/views/search/results/_wiki_blob.html.haml index f9c5810e3d057962ec92eb8f913e3b7b2c93b4ed..c03438eb9525705759a0199609b231e928841eb6 100644 --- a/app/views/search/results/_wiki_blob.html.haml +++ b/app/views/search/results/_wiki_blob.html.haml @@ -1,3 +1,4 @@ +- wiki_blob = @project.repository.parse_search_result(wiki_blob) .blob-result .file-holder .file-title diff --git a/docker/README.md b/docker/README.md index 8df603eca4f0f39d5dedfd64fd255d6986701914..293ca79f915ded71f144820e1bcac6e9af289995 100644 --- a/docker/README.md +++ b/docker/README.md @@ -94,12 +94,12 @@ To upgrade GitLab to new version you have to do: sudo docker stop gitlab ``` -1. stop running container, +1. stop running container, ```bash sudo docker rm gitlab ``` -1. remove existing container, +1. remove existing container, ```bash sudo docker pull gitlab/gitlab-ce:latest ``` @@ -162,4 +162,6 @@ sudo docker push gitlab/gitlab-ce:latest ## Troubleshooting -Please see the [troubleshooting](troubleshooting.md) file in this directory. \ No newline at end of file +Please see the [troubleshooting](troubleshooting.md) file in this directory. + +Note: We use `fig.yml` to have compatibility with fig and because docker-compose also supports it. diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb index 9ad9cb41cc14e3aa3063f9caac50ff26d6d3dbc0..1230017c27099c059004824f6927f6c4a3182a4c 100644 --- a/spec/controllers/autocomplete_controller_spec.rb +++ b/spec/controllers/autocomplete_controller_spec.rb @@ -9,15 +9,27 @@ describe AutocompleteController do before do sign_in(user) project.team << [user, :master] - - get(:users, project_id: project.id) end let(:body) { JSON.parse(response.body) } - it { expect(body).to be_kind_of(Array) } - it { expect(body.size).to eq 1 } - it { expect(body.first["username"]).to eq user.username } + describe 'GET #users with project ID' do + before do + get(:users, project_id: project.id) + end + + it { expect(body).to be_kind_of(Array) } + it { expect(body.size).to eq 1 } + it { expect(body.first["username"]).to eq user.username } + end + + describe 'GET #users with unknown project' do + before do + get(:users, project_id: 'unknown') + end + + it { expect(response.status).to eq(404) } + end end context 'group members' do @@ -26,15 +38,27 @@ describe AutocompleteController do before do sign_in(user) group.add_owner(user) - - get(:users, group_id: group.id) end let(:body) { JSON.parse(response.body) } - it { expect(body).to be_kind_of(Array) } - it { expect(body.size).to eq 1 } - it { expect(body.first["username"]).to eq user.username } + describe 'GET #users with group ID' do + before do + get(:users, group_id: group.id) + end + + it { expect(body).to be_kind_of(Array) } + it { expect(body.size).to eq 1 } + it { expect(body.first["username"]).to eq user.username } + end + + describe 'GET #users with unknown group ID' do + before do + get(:users, group_id: 'unknown') + end + + it { expect(response.status).to eq(404) } + end end context 'all users' do @@ -48,4 +72,52 @@ describe AutocompleteController do it { expect(body).to be_kind_of(Array) } it { expect(body.size).to eq User.count } end + + context 'unauthenticated user' do + let(:public_project) { create(:project, :public) } + let(:body) { JSON.parse(response.body) } + + describe 'GET #users with public project' do + before do + public_project.team << [user, :guest] + get(:users, project_id: public_project.id) + end + + it { expect(body).to be_kind_of(Array) } + it { expect(body.size).to eq 1 } + end + + describe 'GET #users with project' do + before do + get(:users, project_id: project.id) + end + + it { expect(response.status).to eq(302) } + end + + describe 'GET #users with unknown project' do + before do + get(:users, project_id: 'unknown') + end + + it { expect(response.status).to eq(302) } + end + + describe 'GET #users with inaccessible group' do + before do + project.team << [user, :guest] + get(:users, group_id: user.namespace.id) + end + + it { expect(response.status).to eq(302) } + end + + describe 'GET #users with no project' do + before do + get(:users) + end + + it { expect(response.status).to eq(302) } + end + end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index a083dcb127425cc2a9140c73c1c75bbf1f1231bf..d25351b0f0ebd475252c8df428bfaf6f862bf833 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -47,4 +47,28 @@ describe Repository do it { is_expected.to be_falsey } end end + + describe "search_files" do + let(:results) { repository.search_files('feature', 'master') } + subject { results } + + it { is_expected.to be_an Array } + + describe 'result' do + subject { results.first } + + it { is_expected.to be_an String } + it { expect(subject.lines[2]).to eq("master:CHANGELOG:188: - Feature: Replace teams with group membership\n") } + end + + describe 'parsing result' do + subject { repository.parse_search_result(results.first) } + + it { is_expected.to be_an OpenStruct } + it { expect(subject.filename).to eq('CHANGELOG') } + it { expect(subject.ref).to eq('master') } + it { expect(subject.startline).to eq(186) } + it { expect(subject.data.lines[2]).to eq(" - Feature: Replace teams with group membership\n") } + end + end end