From 6e6a99061dbec4bb45a398a03e8a13a084e44035 Mon Sep 17 00:00:00 2001 From: Ted Hogan Date: Mon, 23 Nov 2015 11:36:47 -0700 Subject: [PATCH 01/89] No space required after WIP identifier Modified changelog --- CHANGELOG | 1 + app/models/merge_request.rb | 2 +- spec/models/merge_request_spec.rb | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index fc7b6e75b1..2453b35ead 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.3.0 (unreleased) - Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera) + - WIP identifier on merge requests no longer requires trailing space v 8.2.0 - Improved performance of finding projects and groups in various places diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 1b3d6079d2..2b336ca892 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -239,7 +239,7 @@ class MergeRequest < ActiveRecord::Base end def work_in_progress? - !!(title =~ /\A\[?WIP\]?:? /i) + !!(title =~ /\A\[?WIP(\]|:| )/i) end def mergeable? diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 567c911425..edf211c85c 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -162,6 +162,21 @@ describe MergeRequest do expect(subject).to be_work_in_progress end + it "detects the 'WIP' prefix" do + subject.title = "WIP#{subject.title}" + expect(subject).to be_work_in_progress + end + + it "detects the 'WIP:' prefix" do + subject.title = "WIP:#{subject.title}" + expect(subject).to be_work_in_progress + end + + it "detects the '[WIP]' prefix" do + subject.title = "[WIP]#{subject.title}" + expect(subject).to be_work_in_progress + end + it "doesn't detect WIP for words starting with WIP" do subject.title = "Wipwap #{subject.title}" expect(subject).not_to be_work_in_progress From f0c2f7481febf1e1149cb3dba87780c462759d14 Mon Sep 17 00:00:00 2001 From: Ted Hogan Date: Wed, 6 Jan 2016 10:48:08 -0700 Subject: [PATCH 02/89] Removed redundent and incorrect tests on WIP --- spec/models/merge_request_spec.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 0d3901f4d0..ecfbbb0cfc 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -193,16 +193,6 @@ describe MergeRequest, models: true do expect(subject).to be_work_in_progress end - it "detects the 'WIP' prefix" do - subject.title = "WIP#{subject.title}" - expect(subject).to be_work_in_progress - end - - it "detects the 'WIP:' prefix" do - subject.title = "WIP:#{subject.title}" - expect(subject).to be_work_in_progress - end - it "detects the '[WIP]' prefix" do subject.title = "[WIP]#{subject.title}" expect(subject).to be_work_in_progress From 67a6fee5b124a768279b0681b52be19f138530dc Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 15 Jan 2016 18:12:36 +0100 Subject: [PATCH 03/89] Prototype of Git blobs via workhorse --- app/controllers/projects/raw_controller.rb | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index be7d5c187f..e55cdea94a 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -1,3 +1,5 @@ +require 'base64' + # Controller for viewing a file's raw class Projects::RawController < Projects::ApplicationController include ExtractsPath @@ -15,7 +17,10 @@ class Projects::RawController < Projects::ApplicationController if @blob.lfs_pointer? send_lfs_object else - stream_data + headers['Gitlab-Workhorse-Repo-Path'] = @repository.path_to_repo + headers['Gitlab-Workhorse-Send-Blob'] = Base64.urlsafe_encode64(@commit.id + ':' + @path) + headers['Content-Disposition'] = 'inline' + render nothing: true, content_type: get_blob_type end else render_404 @@ -34,16 +39,6 @@ class Projects::RawController < Projects::ApplicationController end end - def stream_data - type = get_blob_type - - send_data( - @blob.data, - type: type, - disposition: 'inline' - ) - end - def send_lfs_object lfs_object = find_lfs_object From 53ddb8f2ccaa95a19d530827e3fc7500d02ccfff Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 20 Jan 2016 13:44:39 +0100 Subject: [PATCH 04/89] Use a /raw/ request to show an image --- app/views/projects/blob/_image.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/blob/_image.html.haml b/app/views/projects/blob/_image.html.haml index c090f690d1..51fa91b08e 100644 --- a/app/views/projects/blob/_image.html.haml +++ b/app/views/projects/blob/_image.html.haml @@ -1,2 +1,2 @@ .file-content.image_file - %img{ src: "data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}"} + %img{ src: namespace_project_raw_path(@project.namespace, @project, @id)} From d781eee575ffd5e05500e9e2e18c1a2a245a2339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louis=20Roch=C3=A9?= Date: Fri, 22 Jan 2016 14:33:25 +0000 Subject: [PATCH 05/89] Fix typo indentation in CI projects' API --- doc/ci/api/projects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ci/api/projects.md b/doc/ci/api/projects.md index 74a4c64d00..fe6b1c0135 100644 --- a/doc/ci/api/projects.md +++ b/doc/ci/api/projects.md @@ -18,7 +18,7 @@ GET /ci/projects Returns: ```json - [ +[ { "id" : 271, "name" : "gitlabhq", From acfc526828923db381ab01d872ecd1b82618ddc3 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Mon, 25 Jan 2016 06:34:30 +0000 Subject: [PATCH 06/89] update OAuth doc --- doc/integration/oauth_provider.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md index dbe5a175c8..f0c2a45b6a 100644 --- a/doc/integration/oauth_provider.md +++ b/doc/integration/oauth_provider.md @@ -26,7 +26,7 @@ Every application you authorized will be shown in your "Authorized application" ![authorized_application](img/oauth_provider_authorized_application.png) -At any time you can revoke access just clicking button "Revoke" +As you can see we use default scope "api" here which is only scope we have so far. At any time you can revoke access just clicking button "Revoke". ### OAuth applications in admin area From 5287da7412e01ac1508bd15bec5bae7c3a0afa1b Mon Sep 17 00:00:00 2001 From: fbretel Date: Mon, 25 Jan 2016 13:19:27 +0000 Subject: [PATCH 07/89] Consistent rails_socket use. --- lib/support/init.d/gitlab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index 1633891c8a..9e90a99f15 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -219,7 +219,7 @@ start_gitlab() { echo "The Unicorn web server already running with pid $wpid, not restarting." else # Remove old socket if it exists - rm -f "$socket_path"/gitlab.socket 2>/dev/null + rm -f "$rails_socket" 2>/dev/null # Start the web server RAILS_ENV=$RAILS_ENV bin/web start fi From e32eb5715141101a95e97c4f51a2f96976822c9a Mon Sep 17 00:00:00 2001 From: Mike Chelen Date: Wed, 27 Jan 2016 02:10:03 +0000 Subject: [PATCH 08/89] explicitly call script with bash for consistency --- doc/ci/languages/php.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ci/languages/php.md b/doc/ci/languages/php.md index 77f9fae5bb..aeadd6a448 100644 --- a/doc/ci/languages/php.md +++ b/doc/ci/languages/php.md @@ -97,7 +97,7 @@ image: php:5.6 before_script: # Install dependencies -- ci/docker_install.sh > /dev/null +- bash ci/docker_install.sh > /dev/null test:app: script: @@ -112,7 +112,7 @@ with a different docker image version and the runner will do the rest: ```yaml before_script: # Install dependencies -- ci/docker_install.sh > /dev/null +- bash ci/docker_install.sh > /dev/null # We test PHP5.6 test:5.6: From 9109619ee6fe85ee7e8ebfa51c6587319b523930 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 28 Jan 2016 15:02:44 +0100 Subject: [PATCH 09/89] Use less memory while counting lines --- app/views/shared/_file_highlight.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml index 2bc98983d6..331bad3ccf 100644 --- a/app/views/shared/_file_highlight.html.haml +++ b/app/views/shared/_file_highlight.html.haml @@ -1,7 +1,7 @@ .file-content.code.js-syntax-highlight{ class: user_color_scheme } .line-numbers - if blob.data.present? - - blob.data.lines.each_index do |index| + - blob.data.each_line.each_with_index do |_, index| - offset = defined?(first_line_number) ? first_line_number : 1 - i = index + offset -# We're not using `link_to` because it is too slow once we get to thousands of lines. From 26d97ac5e19c242594b59d224a77d41d0f1de6e1 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 28 Jan 2016 18:04:46 +0100 Subject: [PATCH 10/89] Send more raw blob data with workhorse --- app/controllers/projects/avatars_controller.rb | 13 ++++++------- app/controllers/projects/raw_controller.rb | 2 +- lib/api/repositories.rb | 6 ++++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index 548f1b9ebf..0cd65ad5b1 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -2,15 +2,14 @@ class Projects::AvatarsController < Projects::ApplicationController before_action :project def show - @blob = @project.repository.blob_at_branch('master', @project.avatar_in_git) + repository = @project.repository + @blob = repository.blob_at_branch('master', @project.avatar_in_git) if @blob headers['X-Content-Type-Options'] = 'nosniff' - send_data( - @blob.data, - type: @blob.mime_type, - disposition: 'inline', - filename: @blob.name - ) + headers['Gitlab-Workhorse-Repo-Path'] = repository.path_to_repo + headers['Gitlab-Workhorse-Send-Blob'] = @blob.id + headers['Content-Disposition'] = 'inline' + render nothing: true, content_type: @blob.content_type else render_404 end diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index e55cdea94a..b3c846bc3c 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -18,7 +18,7 @@ class Projects::RawController < Projects::ApplicationController send_lfs_object else headers['Gitlab-Workhorse-Repo-Path'] = @repository.path_to_repo - headers['Gitlab-Workhorse-Send-Blob'] = Base64.urlsafe_encode64(@commit.id + ':' + @path) + headers['Gitlab-Workhorse-Send-Blob'] = @blob.id headers['Content-Disposition'] = 'inline' render nothing: true, content_type: get_blob_type end diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index d7c48639eb..0f4cd2443b 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -57,7 +57,8 @@ module API not_found! "File" unless blob content_type 'text/plain' - present blob.data + header 'Gitlab-Workhorse-Repo-Path', repo.path_to_repo + header 'Gitlab-Workhorse-Send-Blob', blob.id end # Get a raw blob contents by blob sha @@ -83,7 +84,8 @@ module API env['api.format'] = :txt content_type blob.mime_type - present blob.data + header 'Gitlab-Workhorse-Repo-Path', repo.path_to_repo + header 'Gitlab-Workhorse-Send-Blob', blob.id end # Get a an archive of the repository From 368b855d88597a48637145838f61113af9c0e98e Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 28 Jan 2016 18:08:37 +0100 Subject: [PATCH 11/89] No need for base64 anymore --- app/controllers/projects/raw_controller.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index b3c846bc3c..b8b9048902 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -1,5 +1,3 @@ -require 'base64' - # Controller for viewing a file's raw class Projects::RawController < Projects::ApplicationController include ExtractsPath From 0197549d57bd32ee933ee775c625ed6fc5f5eec8 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 28 Jan 2016 18:09:52 +0100 Subject: [PATCH 12/89] Cannot see a raw blob without workhorse --- features/steps/project/source/browse_files.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb index d08935aa10..71db552f7b 100644 --- a/features/steps/project/source/browse_files.rb +++ b/features/steps/project/source/browse_files.rb @@ -52,7 +52,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I should see raw file content' do - expect(source).to eq sample_blob.data + expect(source).to eq '' # Body is filled in by gitlab-workhorse end step 'I click button "Edit"' do From fc334e72f40ab5394c70f5cd29829dc3c0b0d485 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 29 Jan 2016 10:28:05 +0000 Subject: [PATCH 13/89] Adds the markdown link at the cursor poisition When writing a comment and then dropping an image it will correctly add the image markdown link at the cursor position Fixes #12822 --- app/assets/javascripts/dropzone_input.js.coffee | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee index c714c0fa93..32a5594a5b 100644 --- a/app/assets/javascripts/dropzone_input.js.coffee +++ b/app/assets/javascripts/dropzone_input.js.coffee @@ -65,8 +65,13 @@ class @DropzoneInput return success: (header, response) -> + link_markdown = response.link.markdown child = $(dropzone[0]).children("textarea") - $(child).val $(child).val() + response.link.markdown + "\n" + cursor_pos = child.prop "selectionStart" + value = $(child).val() + new_text = "#{value.substring(0, cursor_pos)}#{link_markdown}#{value.substring(cursor_pos, value.length)}" + + $(child).val new_text + "\n" return error: (temp, errorMessage) -> From 76534e776e76ef868de7f41fa03bc933882a7b1e Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 29 Jan 2016 15:55:31 +0000 Subject: [PATCH 14/89] Keeps cursor at the correct place after changing text in dropzone --- app/assets/javascripts/dropzone_input.js.coffee | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee index 32a5594a5b..b502131a99 100644 --- a/app/assets/javascripts/dropzone_input.js.coffee +++ b/app/assets/javascripts/dropzone_input.js.coffee @@ -65,13 +65,7 @@ class @DropzoneInput return success: (header, response) -> - link_markdown = response.link.markdown - child = $(dropzone[0]).children("textarea") - cursor_pos = child.prop "selectionStart" - value = $(child).val() - new_text = "#{value.substring(0, cursor_pos)}#{link_markdown}#{value.substring(cursor_pos, value.length)}" - - $(child).val new_text + "\n" + pasteText response.link.markdown return error: (temp, errorMessage) -> @@ -133,6 +127,7 @@ class @DropzoneInput beforeSelection = $(child).val().substring 0, caretStart afterSelection = $(child).val().substring caretEnd, textEnd $(child).val beforeSelection + text + afterSelection + child.get(0).setSelectionRange caretStart + text.length, caretEnd + text.length form_textarea.trigger "input" getFilename = (e) -> From a1e1e72375c6b8f511c779c74b3dd1073afff6c1 Mon Sep 17 00:00:00 2001 From: Warren Guy Date: Sat, 30 Jan 2016 18:30:51 +0800 Subject: [PATCH 15/89] Generate valid Message-ID in email rejection mailer Use a Message-ID that is RFC 2111 compliant. This fix is consistent with how the Message-ID is generated in the 'notify' mailer. --- app/mailers/email_rejection_mailer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/mailers/email_rejection_mailer.rb b/app/mailers/email_rejection_mailer.rb index 883f1c73ad..76db31a4c4 100644 --- a/app/mailers/email_rejection_mailer.rb +++ b/app/mailers/email_rejection_mailer.rb @@ -10,7 +10,7 @@ class EmailRejectionMailer < BaseMailer subject: "[Rejected] #{@original_message.subject}" } - headers['Message-ID'] = SecureRandom.hex + headers['Message-ID'] = "<#{SecureRandom.hex}@#{Gitlab.config.gitlab.host}>" headers['In-Reply-To'] = @original_message.message_id headers['References'] = @original_message.message_id From 026c31dafc80059ec429b484dc28e03e91df2238 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 23 Jan 2016 14:59:22 -0800 Subject: [PATCH 16/89] Bump New Relic gem version to avoid warnings in Web page --- CHANGELOG | 1 + Gemfile | 2 +- Gemfile.lock | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0a21462ebd..a8cbcdfe26 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.5.0 (unreleased) - Ensure rake tasks that don't need a DB connection can be run without one + - Update New Relic gem to 3.14.1.311 (Stan Hu) - Add "visibility" flag to GET /projects api endpoint - Ignore binary files in code search to prevent Error 500 (Stan Hu) - Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push diff --git a/Gemfile b/Gemfile index a09d44f8bf..a1a9c776ae 100644 --- a/Gemfile +++ b/Gemfile @@ -299,7 +299,7 @@ group :production do gem "gitlab_meta", '7.0' end -gem "newrelic_rpm", '~> 3.9.4.245' +gem "newrelic_rpm", '~> 3.14' gem 'newrelic-grape' gem 'octokit', '~> 3.8.0' diff --git a/Gemfile.lock b/Gemfile.lock index ec92964df2..4ca79ccd49 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -481,7 +481,7 @@ GEM newrelic-grape (2.1.0) grape newrelic_rpm - newrelic_rpm (3.9.4.245) + newrelic_rpm (3.14.1.311) nokogiri (1.6.7.2) mini_portile2 (~> 2.0.0.rc2) nprogress-rails (0.1.6.7) @@ -961,7 +961,7 @@ DEPENDENCIES nested_form (~> 0.3.2) net-ssh (~> 3.0.1) newrelic-grape - newrelic_rpm (~> 3.9.4.245) + newrelic_rpm (~> 3.14) nokogiri (= 1.6.7.2) nprogress-rails (~> 0.1.6.7) oauth2 (~> 1.0.0) From 2828274b418cccc8171692495dd2856209dbfa49 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Mon, 25 Jan 2016 21:17:38 -0800 Subject: [PATCH 17/89] Remove newrelic_grape gem since the New Relic gem now provides native support: https://docs.newrelic.com/docs/agents/ruby-agent/frameworks/grape-instrumentation --- Gemfile | 1 - Gemfile.lock | 4 ---- 2 files changed, 5 deletions(-) diff --git a/Gemfile b/Gemfile index a1a9c776ae..0420043e86 100644 --- a/Gemfile +++ b/Gemfile @@ -300,7 +300,6 @@ group :production do end gem "newrelic_rpm", '~> 3.14' -gem 'newrelic-grape' gem 'octokit', '~> 3.8.0' diff --git a/Gemfile.lock b/Gemfile.lock index 4ca79ccd49..981607bdd6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -478,9 +478,6 @@ GEM net-ldap (0.12.1) net-ssh (3.0.1) netrc (0.11.0) - newrelic-grape (2.1.0) - grape - newrelic_rpm newrelic_rpm (3.14.1.311) nokogiri (1.6.7.2) mini_portile2 (~> 2.0.0.rc2) @@ -960,7 +957,6 @@ DEPENDENCIES mysql2 (~> 0.3.16) nested_form (~> 0.3.2) net-ssh (~> 3.0.1) - newrelic-grape newrelic_rpm (~> 3.14) nokogiri (= 1.6.7.2) nprogress-rails (~> 0.1.6.7) From 9040010481e6ab9b1d9ee2d0699dc99d1109f2f2 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 14 Jan 2016 19:16:50 +0000 Subject: [PATCH 18/89] Added dropdown to list all projects on project header When clicking the current project name, it shows a dropdown menu with a list of all projects for that group or user --- app/assets/stylesheets/framework/header.scss | 22 ++++++++++++++- app/helpers/projects_helper.rb | 29 +++++++++++++++++--- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index f875b1460e..0789d8133f 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -73,7 +73,6 @@ header { .title { margin: 0; - overflow: hidden; font-size: 19px; line-height: $header-height; font-weight: normal; @@ -88,6 +87,27 @@ header { text-decoration: underline; } } + + .dropdown { + display: inline-block; + } + + .dropdown-toggle-caret { + margin-left: 5px; + } + + .dropdown-item { + &.active { + .dropdown-link { + color: #fff; + } + } + + .dropdown-link:hover { + color: #fff; + text-decoration: none; + } + } } .navbar-collapse { diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 8c8b355028..5afbdb332c 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -45,6 +45,7 @@ module ProjectsHelper end def project_title(project, name = nil, url = nil) + project_id = project.id namespace_link = if project.group link_to(simple_sanitize(project.group.name), group_path(project.group)) @@ -53,14 +54,34 @@ module ProjectsHelper link_to(simple_sanitize(owner.name), user_path(owner)) end - project_link = link_to(simple_sanitize(project.name), project_path(project)) + all_projects = + if project.group + project.group.projects + else + PersonalProjectsFinder.new(project.namespace.owner).execute(current_user) + end + + project_link = content_tag :div, {class: "dropdown"} do + output = content_tag :a, {class: "dropdown-toggle", href: "#", data: {toggle: "dropdown"}} do + btnOutput = simple_sanitize(project.name) + btnOutput += content_tag :span, nil, {class: "caret dropdown-toggle-caret"} + end + + list = all_projects.map do |project| + content_tag :li, {class: "dropdown-item #{"active" if project_id == project.id}"} do + link_to(simple_sanitize(project.name), project_path(project), {class: "dropdown-link"}) + end + end + + output += content_tag :ul, {class: "dropdown-menu"} do + list.join.html_safe + end + end full_title = namespace_link + ' / ' + project_link full_title += ' · '.html_safe + link_to(simple_sanitize(name), url) if name - content_tag :span do - full_title - end + full_title end def remove_project_message(project) From 14394e8bad388dcb331f16353af46755740b216a Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 07:30:36 +0000 Subject: [PATCH 19/89] pulls in all user projects --- app/assets/stylesheets/framework/header.scss | 8 ++++++++ app/helpers/projects_helper.rb | 13 +++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 0789d8133f..c71c1cbae3 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -92,8 +92,16 @@ header { display: inline-block; } + .dropdown-menu { + max-height: 300px; + overflow: auto; + } + .dropdown-toggle-caret { + position: relative; + top: -2px; margin-left: 5px; + font-size: 10px; } .dropdown-item { diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 5afbdb332c..238bbbbe0a 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -54,22 +54,19 @@ module ProjectsHelper link_to(simple_sanitize(owner.name), user_path(owner)) end - all_projects = - if project.group - project.group.projects - else - PersonalProjectsFinder.new(project.namespace.owner).execute(current_user) - end + all_projects = current_user.authorized_projects.sorted_by_activity.non_archived project_link = content_tag :div, {class: "dropdown"} do output = content_tag :a, {class: "dropdown-toggle", href: "#", data: {toggle: "dropdown"}} do btnOutput = simple_sanitize(project.name) - btnOutput += content_tag :span, nil, {class: "caret dropdown-toggle-caret"} + btnOutput += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} end list = all_projects.map do |project| content_tag :li, {class: "dropdown-item #{"active" if project_id == project.id}"} do - link_to(simple_sanitize(project.name), project_path(project), {class: "dropdown-link"}) + link_to project_path(project), {class: "dropdown-link"} do + project.owner.name + ' / ' + simple_sanitize(project.name) + end end end From 81e7086fec60c368dcd54ff7195f37f6cb8f481c Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 09:13:12 +0000 Subject: [PATCH 20/89] uses AJAX to select the projects --- app/assets/javascripts/project.js.coffee | 10 +++++++++ app/assets/stylesheets/framework/common.scss | 4 ++-- app/assets/stylesheets/framework/header.scss | 22 ------------------- app/helpers/projects_helper.rb | 20 ++++------------- .../shared/_new_project_item_select.html.haml | 8 +++---- 5 files changed, 20 insertions(+), 44 deletions(-) diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index d7a658f8fa..9e31343680 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -50,3 +50,13 @@ class @Project $('#notifications-button').empty().append("" + label + "") $(@).parents('ul').find('li.active').removeClass 'active' $(@).parent().addClass 'active' + + @._projectSelectDropdown() + + _projectSelectDropdown: -> + new ProjectSelect() + + $('.js-projects-dropdown-toggle').on 'click', (e) -> + e.preventDefault() + + $('.js-projects-dropdown').select2 'open' diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 6ea2219073..ea56d9e12a 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -376,11 +376,11 @@ table { margin-bottom: $gl-padding; } -.new-project-item-select-holder { +.project-item-select-holder { display: inline-block; position: relative; - .new-project-item-select { + .project-item-select { position: absolute; top: 0; right: 0; diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index c71c1cbae3..7871a33b6c 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -88,34 +88,12 @@ header { } } - .dropdown { - display: inline-block; - } - - .dropdown-menu { - max-height: 300px; - overflow: auto; - } - .dropdown-toggle-caret { position: relative; top: -2px; margin-left: 5px; font-size: 10px; } - - .dropdown-item { - &.active { - .dropdown-link { - color: #fff; - } - } - - .dropdown-link:hover { - color: #fff; - text-decoration: none; - } - } } .navbar-collapse { diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 238bbbbe0a..c175de9436 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -56,23 +56,11 @@ module ProjectsHelper all_projects = current_user.authorized_projects.sorted_by_activity.non_archived - project_link = content_tag :div, {class: "dropdown"} do - output = content_tag :a, {class: "dropdown-toggle", href: "#", data: {toggle: "dropdown"}} do - btnOutput = simple_sanitize(project.name) - btnOutput += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} - end + project_link = link_to project_path(project), {class: "project-item-select-holder js-projects-dropdown-toggle"} do + link_output = simple_sanitize(project.name) + link_output += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} - list = all_projects.map do |project| - content_tag :li, {class: "dropdown-item #{"active" if project_id == project.id}"} do - link_to project_path(project), {class: "dropdown-link"} do - project.owner.name + ' / ' + simple_sanitize(project.name) - end - end - end - - output += content_tag :ul, {class: "dropdown-menu"} do - list.join.html_safe - end + link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", data: { include_groups: false } end full_title = namespace_link + ' / ' + project_link diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml index c4431d6692..4609591282 100644 --- a/app/views/shared/_new_project_item_select.html.haml +++ b/app/views/shared/_new_project_item_select.html.haml @@ -1,6 +1,6 @@ - if @projects.any? - .prepend-left-10.new-project-item-select-holder - = project_select_tag :project_path, class: "new-project-item-select", data: { include_groups: local_assigns[:include_groups] } + .prepend-left-10.project-item-select-holder + = project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups] } %a.btn.btn-new.new-project-item-select-button = icon('plus') = local_assigns[:label] @@ -8,12 +8,12 @@ :javascript $('.new-project-item-select-button').on('click', function() { - $('.new-project-item-select').select2('open'); + $('.project-item-select').select2('open'); }); var relativePath = '#{local_assigns[:path]}'; - $('.new-project-item-select').on('click', function() { + $('.project-item-select').on('click', function() { window.location = $(this).val() + '/' + relativePath; }); From a5267d0fbdc3e67d7d7cf3445fd1470676accc7a Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 09:17:09 +0000 Subject: [PATCH 21/89] selecting project in dropdown takes user to the correct project --- app/assets/javascripts/project.js.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index 9e31343680..fd7844baac 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -56,6 +56,9 @@ class @Project _projectSelectDropdown: -> new ProjectSelect() + $('.project-item-select').on 'click', -> + window.location = $(this).val() + $('.js-projects-dropdown-toggle').on 'click', (e) -> e.preventDefault() From 60139345403fe2ddeed27a49582800b365606e2c Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 11:08:12 +0000 Subject: [PATCH 22/89] fixes issue when user is not logged in but viewing public project --- app/helpers/projects_helper.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index c175de9436..6c66d0f725 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -54,13 +54,15 @@ module ProjectsHelper link_to(simple_sanitize(owner.name), user_path(owner)) end - all_projects = current_user.authorized_projects.sorted_by_activity.non_archived + all_projects = current_user.authorized_projects.sorted_by_activity.non_archived if current_user - project_link = link_to project_path(project), {class: "project-item-select-holder js-projects-dropdown-toggle"} do + project_link = link_to project_path(project), {class: "project-item-select-holder #{"js-projects-dropdown-toggle" if current_user}"} do link_output = simple_sanitize(project.name) - link_output += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} + link_output += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} if current_user - link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", data: { include_groups: false } + link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", data: { include_groups: false } if current_user + + link_output end full_title = namespace_link + ' / ' + project_link From e79b5ff9d65b5a872bfc69649441d6262ac76b4d Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 11:10:27 +0000 Subject: [PATCH 23/89] removed un-used variable --- app/helpers/projects_helper.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 6c66d0f725..705d1e786f 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -54,8 +54,6 @@ module ProjectsHelper link_to(simple_sanitize(owner.name), user_path(owner)) end - all_projects = current_user.authorized_projects.sorted_by_activity.non_archived if current_user - project_link = link_to project_path(project), {class: "project-item-select-holder #{"js-projects-dropdown-toggle" if current_user}"} do link_output = simple_sanitize(project.name) link_output += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} if current_user From 09dc9bd5686501b2c9847896fee9713cf7cf4aea Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 11:43:49 +0000 Subject: [PATCH 24/89] rubocop fixes --- app/helpers/projects_helper.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 705d1e786f..e7e472cbb5 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -45,7 +45,6 @@ module ProjectsHelper end def project_title(project, name = nil, url = nil) - project_id = project.id namespace_link = if project.group link_to(simple_sanitize(project.group.name), group_path(project.group)) @@ -54,9 +53,9 @@ module ProjectsHelper link_to(simple_sanitize(owner.name), user_path(owner)) end - project_link = link_to project_path(project), {class: "project-item-select-holder #{"js-projects-dropdown-toggle" if current_user}"} do + project_link = link_to project_path(project), { class: "project-item-select-holder #{"js-projects-dropdown-toggle" if current_user}" } do link_output = simple_sanitize(project.name) - link_output += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} if current_user + link_output += content_tag :span, nil, { class: "fa fa-chevron-down dropdown-toggle-caret" } if current_user link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", data: { include_groups: false } if current_user From d34928ca580b9a605f1fb4f0bc0077b99d694d9b Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 13:04:37 +0000 Subject: [PATCH 25/89] remove period from function call --- app/assets/javascripts/project.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index fd7844baac..15c5bfa47e 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -51,7 +51,7 @@ class @Project $(@).parents('ul').find('li.active').removeClass 'active' $(@).parent().addClass 'active' - @._projectSelectDropdown() + @_projectSelectDropdown() _projectSelectDropdown: -> new ProjectSelect() From ad7ec74458523caad5c10108bde620de9a52fe12 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Sun, 17 Jan 2016 14:54:28 +0000 Subject: [PATCH 26/89] removed private method naming --- app/assets/javascripts/project.js.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index 15c5bfa47e..bf987f115a 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -51,9 +51,9 @@ class @Project $(@).parents('ul').find('li.active').removeClass 'active' $(@).parent().addClass 'active' - @_projectSelectDropdown() + @projectSelectDropdown() - _projectSelectDropdown: -> + projectSelectDropdown: -> new ProjectSelect() $('.project-item-select').on 'click', -> From 56b0c46bf6da069be4ea935de4bad35a50e7f3c9 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Sun, 17 Jan 2016 17:19:50 +0000 Subject: [PATCH 27/89] added tests --- app/assets/javascripts/project.js.coffee | 9 ++-- .../fixtures/project_title.html.haml | 7 +++ spec/javascripts/fixtures/projects.json | 1 + spec/javascripts/project_title_spec.js.coffee | 46 +++++++++++++++++++ 4 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 spec/javascripts/fixtures/project_title.html.haml create mode 100644 spec/javascripts/fixtures/projects.json create mode 100644 spec/javascripts/project_title_spec.js.coffee diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index bf987f115a..76bc4ff42a 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -56,10 +56,13 @@ class @Project projectSelectDropdown: -> new ProjectSelect() - $('.project-item-select').on 'click', -> - window.location = $(this).val() + $('.project-item-select').on 'click', (e) => + @changeProject $(e.currentTarget).val() $('.js-projects-dropdown-toggle').on 'click', (e) -> e.preventDefault() - $('.js-projects-dropdown').select2 'open' + $('.js-projects-dropdown').select2('open') + + changeProject: (url) -> + window.location = url diff --git a/spec/javascripts/fixtures/project_title.html.haml b/spec/javascripts/fixtures/project_title.html.haml new file mode 100644 index 0000000000..4286d1be66 --- /dev/null +++ b/spec/javascripts/fixtures/project_title.html.haml @@ -0,0 +1,7 @@ +%h1.title + %a + GitLab Org + %a.project-item-select-holder.js-projects-dropdown-toggle{href: "/gitlab-org/gitlab-test"} + GitLab Test + %span.fa.fa-chevron-down.dropdown-toggle-caret + %input#project_path.project-item-select.js-projects-dropdown.ajax-project-select{type: "hidden", name: "project_path", "data-include-groups" => "false"} diff --git a/spec/javascripts/fixtures/projects.json b/spec/javascripts/fixtures/projects.json new file mode 100644 index 0000000000..84e8d0ba1e --- /dev/null +++ b/spec/javascripts/fixtures/projects.json @@ -0,0 +1 @@ +[{"id":9,"description":"","default_branch":null,"tag_list":[],"public":true,"archived":false,"visibility_level":20,"ssh_url_to_repo":"phil@localhost:root/test.git","http_url_to_repo":"http://localhost:3000/root/test.git","web_url":"http://localhost:3000/root/test","owner":{"name":"Administrator","username":"root","id":1,"state":"active","avatar_url":"http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon","web_url":"http://localhost:3000/u/root"},"name":"test","name_with_namespace":"Administrator / test","path":"test","path_with_namespace":"root/test","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-14T19:08:05.364Z","last_activity_at":"2016-01-14T19:08:07.418Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":1,"name":"root","path":"root","owner_id":1,"created_at":"2016-01-13T20:19:44.439Z","updated_at":"2016-01-13T20:19:44.439Z","description":"","avatar":null},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":0,"permissions":{"project_access":null,"group_access":null}},{"id":8,"description":"Voluptatem quae nulla eius numquam ullam voluptatibus quia modi.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":0,"ssh_url_to_repo":"phil@localhost:h5bp/html5-boilerplate.git","http_url_to_repo":"http://localhost:3000/h5bp/html5-boilerplate.git","web_url":"http://localhost:3000/h5bp/html5-boilerplate","name":"Html5 Boilerplate","name_with_namespace":"H5bp / Html5 Boilerplate","path":"html5-boilerplate","path_with_namespace":"h5bp/html5-boilerplate","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:57.525Z","last_activity_at":"2016-01-13T20:27:57.280Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":5,"name":"H5bp","path":"h5bp","owner_id":null,"created_at":"2016-01-13T20:19:57.239Z","updated_at":"2016-01-13T20:19:57.239Z","description":"Tempore accusantium possimus aut libero.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":{"access_level":10,"notification_level":3},"group_access":{"access_level":50,"notification_level":3}}},{"id":7,"description":"Modi odio mollitia dolorem qui.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":0,"ssh_url_to_repo":"phil@localhost:twitter/typeahead-js.git","http_url_to_repo":"http://localhost:3000/twitter/typeahead-js.git","web_url":"http://localhost:3000/twitter/typeahead-js","name":"Typeahead.Js","name_with_namespace":"Twitter / Typeahead.Js","path":"typeahead-js","path_with_namespace":"twitter/typeahead-js","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:56.212Z","last_activity_at":"2016-01-13T20:27:51.496Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":4,"name":"Twitter","path":"twitter","owner_id":null,"created_at":"2016-01-13T20:19:54.480Z","updated_at":"2016-01-13T20:19:54.480Z","description":"Id voluptatem ipsa maiores omnis repudiandae et et.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":4,"permissions":{"project_access":null,"group_access":{"access_level":10,"notification_level":3}}},{"id":6,"description":"Omnis asperiores ipsa et beatae quidem necessitatibus quia.","default_branch":"master","tag_list":[],"public":true,"archived":false,"visibility_level":20,"ssh_url_to_repo":"phil@localhost:twitter/flight.git","http_url_to_repo":"http://localhost:3000/twitter/flight.git","web_url":"http://localhost:3000/twitter/flight","name":"Flight","name_with_namespace":"Twitter / Flight","path":"flight","path_with_namespace":"twitter/flight","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:54.754Z","last_activity_at":"2016-01-13T20:27:50.502Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":4,"name":"Twitter","path":"twitter","owner_id":null,"created_at":"2016-01-13T20:19:54.480Z","updated_at":"2016-01-13T20:19:54.480Z","description":"Id voluptatem ipsa maiores omnis repudiandae et et.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":4,"permissions":{"project_access":null,"group_access":{"access_level":10,"notification_level":3}}},{"id":5,"description":"Voluptatem commodi voluptate placeat architecto beatae illum dolores fugiat.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":0,"ssh_url_to_repo":"phil@localhost:gitlab-org/gitlab-test.git","http_url_to_repo":"http://localhost:3000/gitlab-org/gitlab-test.git","web_url":"http://localhost:3000/gitlab-org/gitlab-test","name":"Gitlab Test","name_with_namespace":"Gitlab Org / Gitlab Test","path":"gitlab-test","path_with_namespace":"gitlab-org/gitlab-test","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:53.202Z","last_activity_at":"2016-01-13T20:27:41.626Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":3,"name":"Gitlab Org","path":"gitlab-org","owner_id":null,"created_at":"2016-01-13T20:19:48.851Z","updated_at":"2016-01-13T20:19:48.851Z","description":"Magni mollitia quod quidem soluta nesciunt impedit.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":null,"group_access":{"access_level":50,"notification_level":3}}},{"id":4,"description":"Aut molestias quas est ut aperiam officia quod libero.","default_branch":"master","tag_list":[],"public":true,"archived":false,"visibility_level":20,"ssh_url_to_repo":"phil@localhost:gitlab-org/gitlab-shell.git","http_url_to_repo":"http://localhost:3000/gitlab-org/gitlab-shell.git","web_url":"http://localhost:3000/gitlab-org/gitlab-shell","name":"Gitlab Shell","name_with_namespace":"Gitlab Org / Gitlab Shell","path":"gitlab-shell","path_with_namespace":"gitlab-org/gitlab-shell","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:51.882Z","last_activity_at":"2016-01-13T20:27:35.678Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":3,"name":"Gitlab Org","path":"gitlab-org","owner_id":null,"created_at":"2016-01-13T20:19:48.851Z","updated_at":"2016-01-13T20:19:48.851Z","description":"Magni mollitia quod quidem soluta nesciunt impedit.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":{"access_level":20,"notification_level":3},"group_access":{"access_level":50,"notification_level":3}}},{"id":3,"description":"Excepturi molestiae quia repellendus omnis est illo illum eligendi.","default_branch":"master","tag_list":[],"public":true,"archived":false,"visibility_level":20,"ssh_url_to_repo":"phil@localhost:gitlab-org/gitlab-ci.git","http_url_to_repo":"http://localhost:3000/gitlab-org/gitlab-ci.git","web_url":"http://localhost:3000/gitlab-org/gitlab-ci","name":"Gitlab Ci","name_with_namespace":"Gitlab Org / Gitlab Ci","path":"gitlab-ci","path_with_namespace":"gitlab-org/gitlab-ci","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:50.346Z","last_activity_at":"2016-01-13T20:27:30.115Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":3,"name":"Gitlab Org","path":"gitlab-org","owner_id":null,"created_at":"2016-01-13T20:19:48.851Z","updated_at":"2016-01-13T20:19:48.851Z","description":"Magni mollitia quod quidem soluta nesciunt impedit.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":3,"permissions":{"project_access":null,"group_access":{"access_level":50,"notification_level":3}}},{"id":2,"description":"Adipisci quaerat dignissimos enim sed ipsam dolorem quia.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":10,"ssh_url_to_repo":"phil@localhost:gitlab-org/gitlab-ce.git","http_url_to_repo":"http://localhost:3000/gitlab-org/gitlab-ce.git","web_url":"http://localhost:3000/gitlab-org/gitlab-ce","name":"Gitlab Ce","name_with_namespace":"Gitlab Org / Gitlab Ce","path":"gitlab-ce","path_with_namespace":"gitlab-org/gitlab-ce","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:49.065Z","last_activity_at":"2016-01-13T20:26:58.454Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":3,"name":"Gitlab Org","path":"gitlab-org","owner_id":null,"created_at":"2016-01-13T20:19:48.851Z","updated_at":"2016-01-13T20:19:48.851Z","description":"Magni mollitia quod quidem soluta nesciunt impedit.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":{"access_level":30,"notification_level":3},"group_access":{"access_level":50,"notification_level":3}}},{"id":1,"description":"Vel voluptatem maxime saepe ex quia.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":0,"ssh_url_to_repo":"phil@localhost:documentcloud/underscore.git","http_url_to_repo":"http://localhost:3000/documentcloud/underscore.git","web_url":"http://localhost:3000/documentcloud/underscore","name":"Underscore","name_with_namespace":"Documentcloud / Underscore","path":"underscore","path_with_namespace":"documentcloud/underscore","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:45.862Z","last_activity_at":"2016-01-13T20:25:03.106Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":2,"name":"Documentcloud","path":"documentcloud","owner_id":null,"created_at":"2016-01-13T20:19:44.464Z","updated_at":"2016-01-13T20:19:44.464Z","description":"Aut impedit perferendis fuga et ipsa repellat cupiditate et.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":null,"group_access":{"access_level":50,"notification_level":3}}}] diff --git a/spec/javascripts/project_title_spec.js.coffee b/spec/javascripts/project_title_spec.js.coffee new file mode 100644 index 0000000000..47c7b7febe --- /dev/null +++ b/spec/javascripts/project_title_spec.js.coffee @@ -0,0 +1,46 @@ +#= require select2 +#= require api +#= require project_select +#= require project + +window.gon = {} +window.gon.api_version = 'v3' + +describe 'Project Title', -> + fixture.preload('project_title.html') + fixture.preload('projects.json') + + beforeEach -> + fixture.load('project_title.html') + @project = new Project() + + spyOn(@project, 'changeProject').and.callFake (url) -> + window.current_project_url = url + + describe 'project list', -> + beforeEach => + @projects_data = fixture.load('projects.json')[0] + + spyOn(jQuery, 'ajax').and.callFake (req) => + expect(req.url).toBe('/api/v3/projects.json') + d = $.Deferred() + d.resolve @projects_data + d.promise() + + it 'to show on toggle click', => + $('.js-projects-dropdown-toggle').click() + + expect($('.title .select2-container').hasClass('select2-dropdown-open')).toBe(true) + expect($('.ajax-project-dropdown li').length).toBe(@projects_data.length) + + it 'hide dropdown', -> + $("#select2-drop-mask").click() + + expect($('.title .select2-container').hasClass('select2-dropdown-open')).toBe(false) + + it 'change project when clicking item', -> + $('.js-projects-dropdown-toggle').click() + $('.ajax-project-dropdown li:nth-child(2)').trigger('mouseup') + + expect($('.title .select2-container').hasClass('select2-dropdown-open')).toBe(false) + expect(window.current_project_url).toBe('http://localhost:3000/h5bp/html5-boilerplate') From 15bc1a01ab31b4288a3dea429cb7d77d272afbe5 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Sun, 17 Jan 2016 18:12:05 +0000 Subject: [PATCH 28/89] added feature test --- spec/features/projects_spec.rb | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index 9a01c89ae2..ed97b6cb57 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -82,7 +82,26 @@ feature 'Project', feature: true do it 'click project-settings and find leave project' do find('#project-settings-button').click - expect(page).to have_link('Leave Project') + expect(page).to have_link('Leave Project') + end + end + + describe 'project title' do + include WaitForAjax + + let(:user) { create(:user) } + let(:project) { create(:project, namespace: user.namespace) } + + before do + login_with(user) + project.team.add_user(user, Gitlab::Access::MASTER) + visit namespace_project_path(project.namespace, project) + end + + it 'click toggle and show dropdown', js: true do + find('.js-projects-dropdown-toggle').click + wait_for_ajax + expect(page).to have_css('.select2-results li', count: 1) end end From 797bcdf43e19f159492b80ddc635f4bbcf6b41a1 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 31 Jan 2016 15:56:27 -0500 Subject: [PATCH 29/89] Add notes about the regression issues to CONTRIBUTING.md [ci skip] --- CONTRIBUTING.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1bd91f0bdc..a6c85e2a6b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -177,6 +177,26 @@ is probably 1, adding a new Git Hook maybe 4 or 5, big features 7-9. issues or chunks. You can simply not set the weight of a parent issue and set weights to children issues. +### Regression issues + +Every monthly release has a corresponding issue on the CE issue tracker to keep +track of functionality broken by that release and any fixes that need to be +included in a patch release (see [8.3 Regressions] as an example). + +As outlined in the issue description, the intended workflow is to post one note +with a reference to an issue describing the regression, and then to update that +note with a reference to the merge request that fixes it as it becomes available. + +If you're a contributor who doesn't have the required permissions to update +other users' notes, please post a new note with a reference to both the issue +and the merge request. + +The release manager will [update the notes] in the regression issue as fixes are +addressed. + +[8.3 Regressions]: https://gitlab.com/gitlab-org/gitlab-ce/issues/4127 +[update the notes]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue + ## Merge requests We welcome merge requests with fixes and improvements to GitLab code, tests, From 64c8ee47c96d9245081abdf1b9d4ec39cdfc5883 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 10:41:52 +0100 Subject: [PATCH 30/89] WIP lazy blobs --- app/controllers/projects/blob_controller.rb | 3 +++ app/models/ci/commit.rb | 6 +++++- app/models/tree.rb | 2 ++ app/views/projects/blob/_blob.html.haml | 1 + lib/api/files.rb | 6 ++++-- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index c56a3497bb..9045e66873 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -33,6 +33,7 @@ class Projects::BlobController < Projects::ApplicationController def edit @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha + blob.load_all_data!(@repository) end def update @@ -51,6 +52,7 @@ class Projects::BlobController < Projects::ApplicationController def preview @content = params[:content] + @blob.load_all_data!(@repository) diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true) @diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/)) @@ -65,6 +67,7 @@ class Projects::BlobController < Projects::ApplicationController end def diff + @blob.load_all_data!(@repository) @form = UnfoldForm.new(params) @lines = @blob.data.lines[@form.since - 1..@form.to - 1] diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index d2a2923694..96786ac457 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -205,7 +205,11 @@ module Ci end def ci_yaml_file - @ci_yaml_file ||= project.repository.blob_at(sha, '.gitlab-ci.yml').data + return @ci_yaml_file if defined?(@ci_yaml_file) + + blob = project.repository.blob_at(sha, '.gitlab-ci.yml') + blob.load_all_data!(project.repository) + @ci_yaml_file = blob.data rescue nil end diff --git a/app/models/tree.rb b/app/models/tree.rb index e0e04d8859..ecee54c3e0 100644 --- a/app/models/tree.rb +++ b/app/models/tree.rb @@ -31,6 +31,8 @@ class Tree git_repo = repository.raw_repository @readme = Gitlab::Git::Blob.find(git_repo, sha, readme_path) + @readme.load_all_data!(git_repo) + @readme end def trees diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml index 3d8d88834e..50aea96898 100644 --- a/app/views/projects/blob/_blob.html.haml +++ b/app/views/projects/blob/_blob.html.haml @@ -35,6 +35,7 @@ - if blob.lfs_pointer? = render "download", blob: blob - elsif blob.text? + - blob.load_all_data!(@repository) = render "text", blob: blob - elsif blob.image? = render "image", blob: blob diff --git a/lib/api/files.rb b/lib/api/files.rb index 8ad2c1883c..c1d86f313b 100644 --- a/lib/api/files.rb +++ b/lib/api/files.rb @@ -58,9 +58,11 @@ module API commit = user_project.commit(ref) not_found! 'Commit' unless commit - blob = user_project.repository.blob_at(commit.sha, file_path) + repo = user_project.repository + blob = repo.blob_at(commit.sha, file_path) if blob + blob.load_all_data!(repo) status(200) { @@ -72,7 +74,7 @@ module API ref: ref, blob_id: blob.id, commit_id: commit.id, - last_commit_id: user_project.repository.last_commit_for_path(commit.sha, file_path).id + last_commit_id: repo.last_commit_for_path(commit.sha, file_path).id } else not_found! 'File' From 02afa6793cca042f8563b0e26472606c743d76f5 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 11:33:22 +0100 Subject: [PATCH 31/89] Use only one header to send git blobs --- .../projects/avatars_controller.rb | 3 +-- app/controllers/projects/raw_controller.rb | 3 +-- lib/api/repositories.rb | 6 ++---- lib/gitlab/workhorse.rb | 21 +++++++++++++++++++ 4 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 lib/gitlab/workhorse.rb diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index 0cd65ad5b1..eb501c3964 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -6,8 +6,7 @@ class Projects::AvatarsController < Projects::ApplicationController @blob = repository.blob_at_branch('master', @project.avatar_in_git) if @blob headers['X-Content-Type-Options'] = 'nosniff' - headers['Gitlab-Workhorse-Repo-Path'] = repository.path_to_repo - headers['Gitlab-Workhorse-Send-Blob'] = @blob.id + headers.store(*Gitlab::Workhorse.send_git_blob(repository, @blob)) headers['Content-Disposition'] = 'inline' render nothing: true, content_type: @blob.content_type else diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index b8b9048902..2ab8a6b83b 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -15,8 +15,7 @@ class Projects::RawController < Projects::ApplicationController if @blob.lfs_pointer? send_lfs_object else - headers['Gitlab-Workhorse-Repo-Path'] = @repository.path_to_repo - headers['Gitlab-Workhorse-Send-Blob'] = @blob.id + headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) headers['Content-Disposition'] = 'inline' render nothing: true, content_type: get_blob_type end diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index 0f4cd2443b..c95d2d2001 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -57,8 +57,7 @@ module API not_found! "File" unless blob content_type 'text/plain' - header 'Gitlab-Workhorse-Repo-Path', repo.path_to_repo - header 'Gitlab-Workhorse-Send-Blob', blob.id + header *Gitlab::Workhorse.send_git_blob(repo, blob) end # Get a raw blob contents by blob sha @@ -84,8 +83,7 @@ module API env['api.format'] = :txt content_type blob.mime_type - header 'Gitlab-Workhorse-Repo-Path', repo.path_to_repo - header 'Gitlab-Workhorse-Send-Blob', blob.id + header *Gitlab::Workhorse.send_git_blob(repo, blob) end # Get a an archive of the repository diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb new file mode 100644 index 0000000000..ff6fbf0b5c --- /dev/null +++ b/lib/gitlab/workhorse.rb @@ -0,0 +1,21 @@ +require 'base64' +require 'json' + +module Gitlab + class Workhorse + class << self + def send_git_blob(repository, blob) + params_hash = { + 'RepoPath' => repository.path_to_repo, + 'BlobId' => blob.id, + } + params = Base64.urlsafe_encode64(JSON.dump(params_hash)) + + [ + 'Gitlab-Workhorse-Send-Data', + "git-blob:#{params}", + ] + end + end + end +end \ No newline at end of file From b2a634c352ab23ed1180b7678b5c83db0137c0f7 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 12:01:13 +0100 Subject: [PATCH 32/89] Avoid trailing 'charset=' garbage --- app/controllers/projects/avatars_controller.rb | 3 ++- app/controllers/projects/raw_controller.rb | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index eb501c3964..bc40e60103 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -8,7 +8,8 @@ class Projects::AvatarsController < Projects::ApplicationController headers['X-Content-Type-Options'] = 'nosniff' headers.store(*Gitlab::Workhorse.send_git_blob(repository, @blob)) headers['Content-Disposition'] = 'inline' - render nothing: true, content_type: @blob.content_type + headers['Content-Type'] = @blob.content_type + head :ok # 'render nothing: true' messes up the Content-Type else render_404 end diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index 2ab8a6b83b..87b4d08da0 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -17,7 +17,8 @@ class Projects::RawController < Projects::ApplicationController else headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) headers['Content-Disposition'] = 'inline' - render nothing: true, content_type: get_blob_type + headers['Content-Type'] = get_blob_type + head :ok # 'render nothing: true' messes up the Content-Type end else render_404 From b1f22aa35aa62d72f514b3f9beee0a190b6599cc Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 12:27:35 +0100 Subject: [PATCH 33/89] Gotta have newlines --- lib/gitlab/workhorse.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index ff6fbf0b5c..a23120a417 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -18,4 +18,4 @@ module Gitlab end end end -end \ No newline at end of file +end From 1256dabb445211fe48f1d53cc5be15ad99793178 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Mon, 1 Feb 2016 13:54:39 +0100 Subject: [PATCH 34/89] Instrument all Gitlab::Git instance methods --- config/initializers/metrics.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/config/initializers/metrics.rb b/config/initializers/metrics.rb index 0945b93ed5..e69552631f 100644 --- a/config/initializers/metrics.rb +++ b/config/initializers/metrics.rb @@ -49,12 +49,14 @@ if Gitlab::Metrics.enabled? config.instrument_instance_methods(Gitlab::Shell) config.instrument_methods(Gitlab::Git) - config.instrument_instance_methods(Gitlab::Git::Repository) Gitlab::Git.constants.each do |name| const = Gitlab::Git.const_get(name) - config.instrument_methods(const) if const.is_a?(Module) + next unless const.is_a?(Module) + + config.instrument_methods(const) + config.instrument_instance_methods(const) end Dir[Rails.root.join('app', 'finders', '*.rb')].each do |path| From d11d425acc6b6aeaf85113dc9b2aca89b36dfe78 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 14:00:28 +0100 Subject: [PATCH 35/89] Develop with a custom gitlab_git branch --- Gemfile | 2 +- Gemfile.lock | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Gemfile b/Gemfile index a09d44f8bf..88236146a1 100644 --- a/Gemfile +++ b/Gemfile @@ -49,7 +49,7 @@ gem "browser", '~> 1.0.0' # Extracting information from a git repository # Provide access to Gitlab::Git library -gem "gitlab_git", '~> 7.2.23' +gem "gitlab_git", git: 'https://gitlab.com/gitlab-org/gitlab_git.git', branch: 'lazy-blob' # LDAP Auth # GitLab fork with several improvements to original library. For full list of changes diff --git a/Gemfile.lock b/Gemfile.lock index ec92964df2..d6a5fe9dd0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,14 @@ +GIT + remote: https://gitlab.com/gitlab-org/gitlab_git.git + revision: dbf224a5d0404ab094e53144b5e01a88b5e9dbaa + branch: lazy-blob + specs: + gitlab_git (7.2.24) + activesupport (~> 4.0) + charlock_holmes (~> 0.7.3) + github-linguist (~> 4.7.0) + rugged (~> 0.23.3) + GEM remote: https://rubygems.org/ specs: @@ -356,11 +367,6 @@ GEM posix-spawn (~> 0.3) gitlab_emoji (0.2.0) gemojione (~> 2.1) - gitlab_git (7.2.24) - activesupport (~> 4.0) - charlock_holmes (~> 0.7.3) - github-linguist (~> 4.7.0) - rugged (~> 0.23.3) gitlab_meta (7.0) gitlab_omniauth-ldap (1.2.1) net-ldap (~> 0.9) @@ -934,7 +940,7 @@ DEPENDENCIES github-markup (~> 1.3.1) gitlab-flowdock-git-hook (~> 1.0.1) gitlab_emoji (~> 0.2.0) - gitlab_git (~> 7.2.23) + gitlab_git! gitlab_meta (= 7.0) gitlab_omniauth-ldap (~> 1.2.1) gollum-lib (~> 4.1.0) From 29d376025dbca5512a3d8204b262bfb576384b6c Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 14:34:22 +0100 Subject: [PATCH 36/89] Update gitlab_git (lazy-blob branch) --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index d6a5fe9dd0..2c63cca611 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://gitlab.com/gitlab-org/gitlab_git.git - revision: dbf224a5d0404ab094e53144b5e01a88b5e9dbaa + revision: 170a36889aebfd43e3e1e20b6b7661c896816b41 branch: lazy-blob specs: gitlab_git (7.2.24) @@ -350,7 +350,7 @@ GEM json get_process_mem (0.2.0) gherkin-ruby (0.3.2) - github-linguist (4.7.3) + github-linguist (4.7.4) charlock_holmes (~> 0.7.3) escape_utils (~> 1.1.0) mime-types (>= 1.19) From b1a7cb57cd695f1348e38710007f1676e95cce8c Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 14:41:35 +0100 Subject: [PATCH 37/89] Update gitlab_git@lazy-blob again --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2c63cca611..9473e91863 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://gitlab.com/gitlab-org/gitlab_git.git - revision: 170a36889aebfd43e3e1e20b6b7661c896816b41 + revision: 69f2185b8bfc8c54b70a1ce4c8c81d9b9a977ce6 branch: lazy-blob specs: gitlab_git (7.2.24) From 33fb55a572364feca70fcc0f15b80da6176f4d71 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Mon, 1 Feb 2016 15:03:58 +0100 Subject: [PATCH 38/89] Instrument various Rugged constants --- config/initializers/metrics.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/config/initializers/metrics.rb b/config/initializers/metrics.rb index e69552631f..3e1deb8d30 100644 --- a/config/initializers/metrics.rb +++ b/config/initializers/metrics.rb @@ -64,6 +64,16 @@ if Gitlab::Metrics.enabled? config.instrument_instance_methods(const) end + + [ + :Blame, :Branch, :BranchCollection, :Blob, :Commit, :Diff, :Repository, + :Tag, :TagCollection, :Tree + ].each do |name| + const = Rugged.const_get(name) + + config.instrument_methods(const) + config.instrument_instance_methods(const) + end end GC::Profiler.enable From b4e6ee7adc5ad4cb4ab42c5b691684885e2562f1 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 15:19:55 +0100 Subject: [PATCH 39/89] Update development version of gitlab_git --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9473e91863..9aacbced99 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://gitlab.com/gitlab-org/gitlab_git.git - revision: 69f2185b8bfc8c54b70a1ce4c8c81d9b9a977ce6 + revision: 57160e1cbcf4c03e68aa881dfa8e2f55c37a3ee6 branch: lazy-blob specs: gitlab_git (7.2.24) From 72bd004b3114fad43feaa7d21e0c2cde4b5b6a0d Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 16:20:49 +0100 Subject: [PATCH 40/89] Allow "@" in file names and path --- lib/gitlab/regex.rb | 8 ++++---- spec/lib/gitlab/regex_spec.rb | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb index 53ab2686b4..5c35c5b145 100644 --- a/lib/gitlab/regex.rb +++ b/lib/gitlab/regex.rb @@ -44,19 +44,19 @@ module Gitlab def file_name_regex - @file_name_regex ||= /\A[a-zA-Z0-9_\-\.]*\z/.freeze + @file_name_regex ||= /\A[a-zA-Z0-9_\-\.\@]*\z/.freeze end def file_name_regex_message - "can contain only letters, digits, '_', '-' and '.'. " + "can contain only letters, digits, '_', '-', '@' and '.'. " end def file_path_regex - @file_path_regex ||= /\A[a-zA-Z0-9_\-\.\/]*\z/.freeze + @file_path_regex ||= /\A[a-zA-Z0-9_\-\.\/\@]*\z/.freeze end def file_path_regex_message - "can contain only letters, digits, '_', '-' and '.'. Separate directories with a '/'. " + "can contain only letters, digits, '_', '-', '@' and '.'. Separate directories with a '/'. " end diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb index d67ee423b9..c51b10bdc6 100644 --- a/spec/lib/gitlab/regex_spec.rb +++ b/spec/lib/gitlab/regex_spec.rb @@ -21,4 +21,12 @@ describe Gitlab::Regex, lib: true do it { expect('Dash – is this').to match(Gitlab::Regex.project_name_regex) } it { expect('?gitlab').not_to match(Gitlab::Regex.project_name_regex) } end + + describe 'file name regex' do + it { expect('foo@bar').to match(Gitlab::Regex.file_name_regex) } + end + + describe 'file path regex' do + it { expect('foo@/bar').to match(Gitlab::Regex.file_path_regex) } + end end From e6cb010088c92a4c26fd2ac201944327369e7803 Mon Sep 17 00:00:00 2001 From: Aral Balkan Date: Sat, 25 Jul 2015 10:39:49 +0000 Subject: [PATCH 41/89] Added note: working copy changes (e.g., deleted vendor folder) should be stashed before beginning the update process. We should probably include this notice on all update guides. [ci skip] --- doc/update/6.x-or-7.x-to-7.14.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/update/6.x-or-7.x-to-7.14.md b/doc/update/6.x-or-7.x-to-7.14.md index 4516a10208..c45fc9340e 100644 --- a/doc/update/6.x-or-7.x-to-7.14.md +++ b/doc/update/6.x-or-7.x-to-7.14.md @@ -14,6 +14,12 @@ possible to edit the label text and color. The characters `?`, `&` and `,` are no longer allowed however so those will be removed from your tags during the database migrations for GitLab 7.2. +## Stash changes + +If you [deleted the vendors folder during your original installation](https://github.com/gitlabhq/gitlabhq/issues/4883#issuecomment-31108431), [you will get an error](https://gitlab.com/gitlab-org/gitlab-ce/issues/1494) when you attempt to rebuild the assets in step 7. To avoid this, stash the changes in your GitLab working copy before starting: + + git stash + ## 0. Stop server sudo service gitlab stop From 06c0025f16480fce831362317ed6427d51ab3c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 1 Feb 2016 19:10:25 +0100 Subject: [PATCH 42/89] Improving the "Environment variables" administration doc --- config/database.yml.env | 12 ++++- doc/administration/environment_variables.md | 60 ++++++++++----------- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/config/database.yml.env b/config/database.yml.env index b2ff23cb5a..1e35651c9a 100644 --- a/config/database.yml.env +++ b/config/database.yml.env @@ -1,9 +1,17 @@ <%= ENV['RAILS_ENV'] %>: + ## Connection information + # Please be aware that the DATABASE_URL environment variable will take + # precedence over the following 6 parameters. For more information, see + # doc/administration/environment_variables.md adapter: <%= ENV['GITLAB_DATABASE_ADAPTER'] || 'postgresql' %> - encoding: <%= ENV['GITLAB_DATABASE_ENCODING'] || 'unicode' %> database: <%= ENV['GITLAB_DATABASE_DATABASE'] || "gitlab_#{ENV['RAILS_ENV']}" %> - pool: <%= ENV['GITLAB_DATABASE_POOL'] || '10' %> username: <%= ENV['GITLAB_DATABASE_USERNAME'] || 'root' %> password: <%= ENV['GITLAB_DATABASE_PASSWORD'] || '' %> host: <%= ENV['GITLAB_DATABASE_HOST'] || 'localhost' %> port: <%= ENV['GITLAB_DATABASE_PORT'] || '5432' %> + + ## Behavior information + # The following parameters will be used even if you're using the DATABASE_URL + # environment variable. + encoding: <%= ENV['GITLAB_DATABASE_ENCODING'] || 'unicode' %> + pool: <%= ENV['GITLAB_DATABASE_POOL'] || '10' %> diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md index 0faef526d4..b0aa420e05 100644 --- a/doc/administration/environment_variables.md +++ b/doc/administration/environment_variables.md @@ -2,7 +2,7 @@ ## Introduction -Commonly people configure GitLab via the gitlab.rb configuration file in the Omnibus package. +Commonly people configure GitLab via the `gitlab.rb` configuration file in the Omnibus package. But if you prefer to use environment variables we allow that too. @@ -10,45 +10,45 @@ But if you prefer to use environment variables we allow that too. Variable | Type | Explanation -------- | ---- | ----------- -GITLAB_ROOT_PASSWORD | string | sets the password for the `root` user on installation -GITLAB_HOST | url | hostname of the GitLab server includes http or https -RAILS_ENV | production / development / staging / test | Rails environment -DATABASE_URL | url | For example: postgresql://localhost/blog_development?pool=5 -GITLAB_EMAIL_FROM | email | Email address used in the "From" field in mails sent by GitLab -GITLAB_EMAIL_DISPLAY_NAME | string | Name used in the "From" field in mails sent by GitLab -GITLAB_EMAIL_REPLY_TO | email | Email address used in the "Reply-To" field in mails sent by GitLab -GITLAB_UNICORN_MEMORY_MIN | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer -GITLAB_UNICORN_MEMORY_MAX | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer +`GITLAB_ROOT_PASSWORD` | string | Sets the password for the `root` user on installation +`GITLAB_HOST` | url | Hostname of the GitLab server includes http or https +`RAILS_ENV` | production / development / staging / test | Rails environment +`DATABASE_URL` | url | For example: postgresql://localhost/blog_development +`GITLAB_EMAIL_FROM` | email | Email address used in the "From" field in mails sent by GitLab +`GITLAB_EMAIL_DISPLAY_NAME` | string | Name used in the "From" field in mails sent by GitLab +`GITLAB_EMAIL_REPLY_TO` | email | Email address used in the "Reply-To" field in mails sent by GitLab +`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer +`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer ## Complete database variables -As explained in the [Heroku documentation](https://devcenter.heroku.com/articles/rails-database-connection-behavior) the DATABASE_URL doesn't let you set: +The recommended way of specifying your database connection information is to set +the `DATABASE_URL` environment variable. This variable only holds connection +information (adapter, database, username, password, host and port), but not +behavior information (encoding, pool). If you don't want to use `DATABASE_URL` +and/or want to set database behavior information, you will have to: -- adapter -- database -- username -- password -- host -- port +- copy our template `config/database.yml` file: `cp config/database.yml.env config/database.yml` +- set a value for some `GITLAB_DATABASE_XXX` variables -To do so please `cp config/database.yml.env config/database.yml` and use the following variables: +The list of `GITLAB_DATABASE_XXX` variables that you can set is as follow: -Variable | Default ---- | --- -GITLAB_DATABASE_ADAPTER | postgresql -GITLAB_DATABASE_ENCODING | unicode -GITLAB_DATABASE_DATABASE | gitlab_#{ENV['RAILS_ENV'] -GITLAB_DATABASE_POOL | 10 -GITLAB_DATABASE_USERNAME | root -GITLAB_DATABASE_PASSWORD | -GITLAB_DATABASE_HOST | localhost -GITLAB_DATABASE_PORT | 5432 +Variable | Default value | Overridden by `DATABASE_URL`? +--- | --- | --- +`GITLAB_DATABASE_ADAPTER` | `postgresql` | Yes +`GITLAB_DATABASE_DATABASE` | `gitlab_#{ENV['RAILS_ENV']` | Yes +`GITLAB_DATABASE_USERNAME` | `root` | Yes +`GITLAB_DATABASE_PASSWORD` | None | Yes +`GITLAB_DATABASE_HOST` | `localhost` | Yes +`GITLAB_DATABASE_PORT` | `5432` | Yes +`GITLAB_DATABASE_ENCODING` | `unicode` | No +`GITLAB_DATABASE_POOL` | `10` | No ## Adding more variables We welcome merge requests to make more settings configurable via variables. -Please make changes in the file config/initializers/1_settings.rb -Please stick to the naming scheme "GITLAB_#{name 1_settings.rb in upper case}". +Please make changes in the `config/initializers/1_settings.rb` file. +Please stick to the naming scheme `GITLAB_#{name in 1_settings.rb in upper case}`. ## Omnibus configuration From 9dfc4511ff1b8029ce8ad4e6c94bc0f39164b02d Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 28 Jan 2016 11:49:41 +0100 Subject: [PATCH 43/89] Updated contributing guide for stable releases Fixes #12784 --- CONTRIBUTING.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e7659b06c7..4130c57d47 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -257,6 +257,18 @@ Please ensure that your merge request meets the contribution acceptance criteria When having your code reviewed and when reviewing merge requests please take the [thoughtbot code review guidelines](https://github.com/thoughtbot/guides/tree/master/code-review) into account. +## Changes for Stable Releases + +Sometimes certain changes have to be added to an existing stable release. +Two examples are bug fixes and performance improvements. In these cases the +corresponding merge request should be updated to have the following: + +1. A milestone indicating what release the merge request should be merged into. +1. The label "Pick into Stable" + +This makes it easier for release managers to keep track of what still has to be +merged and where changes have to be merged into. + ## Definition of done If you contribute to GitLab please know that changes involve more than just From 7eb961f0816fd8be628162ca58a5377aae7ac165 Mon Sep 17 00:00:00 2001 From: Zeger-Jan van de Weg Date: Tue, 2 Feb 2016 11:17:20 +0100 Subject: [PATCH 44/89] Improve tooltips on admin menu --- app/views/layouts/nav/_admin.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index cffdb52cc2..62e6fba5e3 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -1,6 +1,6 @@ %ul.nav.nav-sidebar = nav_link(controller: :dashboard, html_options: {class: 'home'}) do - = link_to admin_root_path, title: "Stats" do + = link_to admin_root_path, title: 'Overview' do = icon('dashboard fw') %span Overview @@ -25,13 +25,13 @@ %span Deploy Keys = nav_link path: ['runners#index', 'runners#show'] do - = link_to admin_runners_path do + = link_to admin_runners_path, title: 'Runners' do = icon('cog fw') %span Runners %span.count= number_with_delimiter(Ci::Runner.count(:all)) = nav_link path: 'builds#index' do - = link_to admin_builds_path do + = link_to admin_builds_path, title: 'Builds' do = icon('link fw') %span Builds From c76e6b982bb171f24592b62264b28eb3fbe1bafc Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 14:17:08 +0100 Subject: [PATCH 45/89] Move load command into _text partial --- app/views/projects/blob/_blob.html.haml | 1 - app/views/projects/blob/_text.html.haml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml index 50aea96898..3d8d88834e 100644 --- a/app/views/projects/blob/_blob.html.haml +++ b/app/views/projects/blob/_blob.html.haml @@ -35,7 +35,6 @@ - if blob.lfs_pointer? = render "download", blob: blob - elsif blob.text? - - blob.load_all_data!(@repository) = render "text", blob: blob - elsif blob.image? = render "image", blob: blob diff --git a/app/views/projects/blob/_text.html.haml b/app/views/projects/blob/_text.html.haml index 906e5ccb36..d09cd73558 100644 --- a/app/views/projects/blob/_text.html.haml +++ b/app/views/projects/blob/_text.html.haml @@ -1,3 +1,4 @@ +- blob.load_all_data!(@repository) - if markup?(blob.name) .file-content.wiki = render_markup(blob.name, blob.data) From d20e75a8d80c2828336cd22897ea6868d666f8a5 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 9 Jan 2016 19:30:34 +0000 Subject: [PATCH 46/89] Support Akismet spam checking for creation of issues via API Currently any spam detected by Akismet by non-members via API will be logged in a separate table in the admin page. Closes #5612 --- CHANGELOG | 1 + Gemfile | 3 +- Gemfile.lock | 2 + .../admin/application_settings_controller.rb | 2 + app/controllers/admin/spam_logs_controller.rb | 33 ++++++++++++ app/models/application_setting.rb | 8 ++- app/models/spam_log.rb | 13 +++++ app/models/spam_report.rb | 5 ++ app/models/user.rb | 1 + app/services/create_spam_log_service.rb | 13 +++++ .../application_settings/_form.html.haml | 23 +++++++-- app/views/admin/spam_logs/_spam_log.html.haml | 30 +++++++++++ app/views/admin/spam_logs/index.html.haml | 21 ++++++++ app/views/layouts/nav/_admin.html.haml | 7 +++ config/routes.rb | 2 + ...326_add_akismet_to_application_settings.rb | 8 +++ db/migrate/20160109054846_create_spam_logs.rb | 16 ++++++ db/schema.rb | 15 ++++++ doc/integration/README.md | 1 + doc/integration/akismet.md | 30 +++++++++++ doc/integration/img/akismet_settings.png | Bin 0 -> 55837 bytes features/admin/spam_logs.feature | 8 +++ features/steps/admin/spam_logs.rb | 18 +++++++ features/steps/shared/paths.rb | 4 ++ lib/api/issues.rb | 22 +++++++- lib/gitlab/akismet_helper.rb | 39 +++++++++++++++ lib/gitlab/current_settings.rb | 3 +- .../admin/spam_logs_controller_spec.rb | 47 ++++++++++++++++++ spec/factories/spam_logs.rb | 7 +++ spec/lib/gitlab/akismet_helper_spec.rb | 35 +++++++++++++ spec/requests/api/issues_spec.rb | 22 ++++++++ 31 files changed, 432 insertions(+), 7 deletions(-) create mode 100644 app/controllers/admin/spam_logs_controller.rb create mode 100644 app/models/spam_log.rb create mode 100644 app/models/spam_report.rb create mode 100644 app/services/create_spam_log_service.rb create mode 100644 app/views/admin/spam_logs/_spam_log.html.haml create mode 100644 app/views/admin/spam_logs/index.html.haml create mode 100644 db/migrate/20151231152326_add_akismet_to_application_settings.rb create mode 100644 db/migrate/20160109054846_create_spam_logs.rb create mode 100644 doc/integration/akismet.md create mode 100644 doc/integration/img/akismet_settings.png create mode 100644 features/admin/spam_logs.feature create mode 100644 features/steps/admin/spam_logs.rb create mode 100644 lib/gitlab/akismet_helper.rb create mode 100644 spec/controllers/admin/spam_logs_controller_spec.rb create mode 100644 spec/factories/spam_logs.rb create mode 100644 spec/lib/gitlab/akismet_helper_spec.rb diff --git a/CHANGELOG b/CHANGELOG index 7a70516173..1be1f7374d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -74,6 +74,7 @@ v 8.4.0 - Don't notify users twice if they are both project watchers and subscribers (Stan Hu) - Remove gray background from layout in UI - Fix signup for OAuth providers that don't provide a name + - Support Akismet spam checking for creation of issues via API (Stan Hu) - Implement new UI for group page - Implement search inside emoji picker - Let the CI runner know about builds that this build depends on diff --git a/Gemfile b/Gemfile index c9d428a179..9f012e1a7e 100644 --- a/Gemfile +++ b/Gemfile @@ -36,8 +36,9 @@ gem 'omniauth-twitter', '~> 1.2.0' gem 'omniauth_crowd', '~> 2.2.0' gem 'rack-oauth2', '~> 1.2.1' -# reCAPTCHA protection +# Spam and anti-bot protection gem 'recaptcha', require: 'recaptcha/rails' +gem 'akismet', '~> 2.0' # Two-factor authentication gem 'devise-two-factor', '~> 2.0.0' diff --git a/Gemfile.lock b/Gemfile.lock index b4f7587c41..9570d387f6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -49,6 +49,7 @@ GEM addressable (2.3.8) after_commit_queue (1.3.0) activerecord (>= 3.0) + akismet (2.0.0) allocations (1.0.3) annotate (2.6.10) activerecord (>= 3.2, <= 4.3) @@ -884,6 +885,7 @@ DEPENDENCIES acts-as-taggable-on (~> 3.4) addressable (~> 2.3.8) after_commit_queue + akismet (~> 2.0) allocations (~> 1.0) annotate (~> 2.6.0) asana (~> 0.4.0) diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 9943745208..1515086b16 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -79,6 +79,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :recaptcha_private_key, :sentry_enabled, :sentry_dsn, + :akismet_enabled, + :akismet_api_key, restricted_visibility_levels: [], import_sources: [] ) diff --git a/app/controllers/admin/spam_logs_controller.rb b/app/controllers/admin/spam_logs_controller.rb new file mode 100644 index 0000000000..69f94dd3ba --- /dev/null +++ b/app/controllers/admin/spam_logs_controller.rb @@ -0,0 +1,33 @@ +class Admin::SpamLogsController < Admin::ApplicationController + before_action :set_spam_log, only: [:destroy] + + def index + @spam_logs = SpamLog.order(created_at: :desc).page(params[:page]) + end + + def destroy + @spam_log.destroy + message = 'Spam log was successfully destroyed.' + + if params[:remove_user] + username = @spam_log.user.username + @spam_log.user.destroy + message = "User #{username} was successfully destroyed." + end + + respond_to do |format| + format.json { render json: '{}' } + format.html { redirect_to admin_spam_logs_path, notice: message } + end + end + + private + + def set_spam_log + @spam_log = SpamLog.find(params[:id]) + end + + def spam_log_params + params[:spam_log] + end +end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 59563b8823..9cafc78f76 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -88,6 +88,10 @@ class ApplicationSetting < ActiveRecord::Base presence: true, if: :sentry_enabled + validates :akismet_api_key, + presence: true, + if: :akismet_enabled + validates_each :restricted_visibility_levels do |record, attr, value| unless value.nil? value.each do |level| @@ -143,7 +147,9 @@ class ApplicationSetting < ActiveRecord::Base shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'], max_artifacts_size: Settings.artifacts['max_size'], require_two_factor_authentication: false, - two_factor_grace_period: 48 + two_factor_grace_period: 48, + recaptcha_enabled: false, + akismet_enabled: false ) end diff --git a/app/models/spam_log.rb b/app/models/spam_log.rb new file mode 100644 index 0000000000..132c5713e0 --- /dev/null +++ b/app/models/spam_log.rb @@ -0,0 +1,13 @@ +class SpamLog < ActiveRecord::Base + belongs_to :user + + validates :user, presence: true + + def truncated_description + if description.present? && description.length > 100 + return description[0..100] + "..." + end + + description + end +end diff --git a/app/models/spam_report.rb b/app/models/spam_report.rb new file mode 100644 index 0000000000..cdc7321b08 --- /dev/null +++ b/app/models/spam_report.rb @@ -0,0 +1,5 @@ +class SpamReport < ActiveRecord::Base + belongs_to :user + + validates :user, presence: true +end diff --git a/app/models/user.rb b/app/models/user.rb index 4214f01f6a..63c895683f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -138,6 +138,7 @@ class User < ActiveRecord::Base has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy has_one :abuse_report, dependent: :destroy + has_many :spam_log, dependent: :destroy has_many :builds, dependent: :nullify, class_name: 'Ci::Build' diff --git a/app/services/create_spam_log_service.rb b/app/services/create_spam_log_service.rb new file mode 100644 index 0000000000..59a66fde47 --- /dev/null +++ b/app/services/create_spam_log_service.rb @@ -0,0 +1,13 @@ +class CreateSpamLogService < BaseService + def initialize(project, user, params) + super(project, user, params) + end + + def execute + spam_params = params.merge({ user_id: @current_user.id, + project_id: @project.id } ) + spam_log = SpamLog.new(spam_params) + spam_log.save + spam_log + end +end diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index b0f1a34cbe..b4e3d96d40 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -218,20 +218,37 @@ = f.label :recaptcha_enabled do = f.check_box :recaptcha_enabled Enable reCAPTCHA - %span.help-block#recaptcha_help_block Helps preventing bots from creating accounts + %span.help-block#recaptcha_help_block Helps prevent bots from creating accounts .form-group = f.label :recaptcha_site_key, 'reCAPTCHA Site Key', class: 'control-label col-sm-2' .col-sm-10 = f.text_field :recaptcha_site_key, class: 'form-control' .help-block - Generate site and private keys here: - %a{ href: 'http://www.google.com/recaptcha', target: '_blank'} http://www.google.com/recaptcha + Generate site and private keys at + %a{ href: 'http://www.google.com/recaptcha', target: 'blank'} http://www.google.com/recaptcha + .form-group = f.label :recaptcha_private_key, 'reCAPTCHA Private Key', class: 'control-label col-sm-2' .col-sm-10 = f.text_field :recaptcha_private_key, class: 'form-control' + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :akismet_enabled do + = f.check_box :akismet_enabled + Enable Akismet + %span.help-block#akismet_help_block Helps prevent bots from creating issues + + .form-group + = f.label :akismet_api_key, 'Akismet API Key', class: 'control-label col-sm-2' + .col-sm-10 + = f.text_field :akismet_api_key, class: 'form-control' + .help-block + Generate API key at + %a{ href: 'http://www.akismet.com', target: 'blank'} http://www.akismet.com + %fieldset %legend Error Reporting and Logging %p diff --git a/app/views/admin/spam_logs/_spam_log.html.haml b/app/views/admin/spam_logs/_spam_log.html.haml new file mode 100644 index 0000000000..1c793bbf73 --- /dev/null +++ b/app/views/admin/spam_logs/_spam_log.html.haml @@ -0,0 +1,30 @@ +- user = spam_log.user +%tr + %td + = spam_log.created_at.to_s(:short) + %td + - if user + = link_to user.name, user + - else + (removed) + %td + = spam_log.source_ip + %td + = spam_log.via_api ? 'Y' : 'N' + %td + = spam_log.noteable_type + %td + = spam_log.title + %td + = spam_log.truncated_description + %td + - if user + = link_to 'Remove user', admin_spam_log_path(spam_log, remove_user: true), + data: { confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?" }, method: :delete, class: "btn btn-xs btn-remove" + %td + - if user && !user.blocked? + = link_to 'Block user', block_admin_user_path(user), data: {confirm: 'USER WILL BE BLOCKED! Are you sure?'}, method: :put, class: "btn btn-xs" + - else + .btn.btn-xs.disabled + Already Blocked + = link_to 'Remove log', [:admin, spam_log, format: :json], remote: true, method: :delete, class: "btn btn-xs btn-close js-remove-tr" diff --git a/app/views/admin/spam_logs/index.html.haml b/app/views/admin/spam_logs/index.html.haml new file mode 100644 index 0000000000..439468e572 --- /dev/null +++ b/app/views/admin/spam_logs/index.html.haml @@ -0,0 +1,21 @@ +- page_title "Spam Logs" +%h3.page-title Spam Logs +%hr +- if @spam_logs.present? + .table-holder + %table.table + %thead + %tr + %th Date + %th User + %th Source IP + %th Via API? + %th Type + %th Title + %th Description + %th Primary Action + %th + = render @spam_logs + = paginate @spam_logs +- else + %h4 There are no Spam Logs diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index cffdb52cc2..8dc2058742 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -82,6 +82,13 @@ Abuse Reports %span.count= number_with_delimiter(AbuseReport.count(:all)) + = nav_link(controller: :spam_logs) do + = link_to admin_spam_logs_path, title: "Spam Logs" do + = icon('exclamation-triangle fw') + %span + Spam Logs + %span.count= number_with_delimiter(SpamLog.count(:all)) + = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do = link_to admin_application_settings_path, title: 'Settings' do = icon('cogs fw') diff --git a/config/routes.rb b/config/routes.rb index 54cc338b60..034bfaf1bc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -211,6 +211,8 @@ Rails.application.routes.draw do end resources :abuse_reports, only: [:index, :destroy] + resources :spam_logs, only: [:index, :destroy] + resources :applications resources :groups, constraints: { id: /[^\/]+/ } do diff --git a/db/migrate/20151231152326_add_akismet_to_application_settings.rb b/db/migrate/20151231152326_add_akismet_to_application_settings.rb new file mode 100644 index 0000000000..3f52c758f9 --- /dev/null +++ b/db/migrate/20151231152326_add_akismet_to_application_settings.rb @@ -0,0 +1,8 @@ +class AddAkismetToApplicationSettings < ActiveRecord::Migration + def change + change_table :application_settings do |t| + t.boolean :akismet_enabled, default: false + t.string :akismet_api_key + end + end +end diff --git a/db/migrate/20160109054846_create_spam_logs.rb b/db/migrate/20160109054846_create_spam_logs.rb new file mode 100644 index 0000000000..f12fe9f8f7 --- /dev/null +++ b/db/migrate/20160109054846_create_spam_logs.rb @@ -0,0 +1,16 @@ +class CreateSpamLogs < ActiveRecord::Migration + def change + create_table :spam_logs do |t| + t.integer :user_id + t.string :source_ip + t.string :user_agent + t.boolean :via_api + t.integer :project_id + t.string :noteable_type + t.string :title + t.text :description + + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 2ad2c23fba..d546e06cd8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -64,6 +64,8 @@ ActiveRecord::Schema.define(version: 20160128233227) do t.integer "metrics_sample_interval", default: 15 t.boolean "sentry_enabled", default: false t.string "sentry_dsn" + t.boolean "akismet_enabled", default: false + t.string "akismet_api_key" end create_table "audit_events", force: :cascade do |t| @@ -770,6 +772,19 @@ ActiveRecord::Schema.define(version: 20160128233227) do add_index "snippets", ["project_id"], name: "index_snippets_on_project_id", using: :btree add_index "snippets", ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree + create_table "spam_logs", force: :cascade do |t| + t.integer "user_id" + t.string "source_ip" + t.string "user_agent" + t.boolean "via_api" + t.integer "project_id" + t.string "noteable_type" + t.string "title" + t.text "description" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "subscriptions", force: :cascade do |t| t.integer "user_id" t.integer "subscribable_id" diff --git a/doc/integration/README.md b/doc/integration/README.md index 83116bc837..281eea8363 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -15,6 +15,7 @@ See the documentation below for details on how to configure these services. - [OAuth2 provider](oauth_provider.md) OAuth2 application creation - [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages - [reCAPTCHA](recaptcha.md) Configure GitLab to use Google reCAPTCHA for new users +- [Akismet](akismet.md) Configure Akismet to stop spam GitLab Enterprise Edition contains [advanced Jenkins support][jenkins]. diff --git a/doc/integration/akismet.md b/doc/integration/akismet.md new file mode 100644 index 0000000000..5cc09bd536 --- /dev/null +++ b/doc/integration/akismet.md @@ -0,0 +1,30 @@ +# Akismet + +GitLab leverages [Akismet](http://akismet.com) to protect against spam. Currently +GitLab uses Akismet to prevent users who are not members of a project from +creating spam via the GitLab API. Detected spam will be rejected, and +an entry in the "Spam Log" section in the Admin page will be created. + +Privacy note: GitLab submits the user's IP and user agent to Akismet. Note that +adding a user to a project will disable the Akismet check and prevent this +from happening. + +## Configuration + +To use Akismet: + +1. Go to the URL: https://akismet.com/account/ + +2. Sign-in or create a new account. + +3. Click on "Show" to reveal the API key. + +4. Go to Applications Settings on Admin Area (`admin/application_settings`) + +5. Check the `Enable Akismet` checkbox + +6. Fill in the API key from step 3. + +7. Save the configuration. + +![Screenshot of Akismet settings](img/akismet_settings.png) diff --git a/doc/integration/img/akismet_settings.png b/doc/integration/img/akismet_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..ccdd3adb1c57acee6fbd9efc4bd8556815a75676 GIT binary patch literal 55837 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 Bwp#!I literal 0 HcmV?d00001 diff --git a/features/admin/spam_logs.feature b/features/admin/spam_logs.feature new file mode 100644 index 0000000000..92a5389e3a --- /dev/null +++ b/features/admin/spam_logs.feature @@ -0,0 +1,8 @@ +Feature: Admin spam logs + Background: + Given I sign in as an admin + And spam logs exist + + Scenario: Browse spam logs + When I visit spam logs page + Then I should see list of spam logs diff --git a/features/steps/admin/spam_logs.rb b/features/steps/admin/spam_logs.rb new file mode 100644 index 0000000000..79d18b036b --- /dev/null +++ b/features/steps/admin/spam_logs.rb @@ -0,0 +1,18 @@ +class Spinach::Features::AdminSpamLogs < Spinach::FeatureSteps + include SharedAuthentication + include SharedPaths + include SharedAdmin + + step 'I should see list of spam logs' do + page.should have_content("Spam Logs") + spam_log = SpamLog.first + page.should have_content spam_log.title + page.should have_content spam_log.description + page.should have_link("Remove user") + page.should have_link("Block user") + end + + step 'spam logs exist' do + create(:spam_log) + end +end diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index 4264c9c6f1..2c854ac7bf 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -191,6 +191,10 @@ module SharedPaths visit admin_application_settings_path end + step 'I visit spam logs page' do + visit admin_spam_logs_path + end + step 'I visit applications page' do visit admin_applications_path end diff --git a/lib/api/issues.rb b/lib/api/issues.rb index 6e7a767207..cdadd13c13 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -3,6 +3,8 @@ module API class Issues < Grape::API before { authenticate! } + helpers ::Gitlab::AkismetHelper + helpers do def filter_issues_state(issues, state) case state @@ -19,6 +21,15 @@ module API def filter_issues_milestone(issues, milestone) issues.includes(:milestone).where('milestones.title' => milestone) end + + def create_spam_log(project, current_user, attrs) + params = attrs.dup + params[:source_ip] = env['REMOTE_ADDR'] + params[:user_agent] = env['HTTP_USER_AGENT'] + params[:noteable_type] = 'Issue' + params[:via_api] = true + ::CreateSpamLogService.new(project, current_user, params).execute + end end resource :issues do @@ -114,7 +125,16 @@ module API render_api_error!({ labels: errors }, 400) end - issue = ::Issues::CreateService.new(user_project, current_user, attrs).execute + project = user_project + text = attrs[:title] + text += "\n#{attrs[:description]}" if attrs[:description].present? + + if check_for_spam?(project, current_user) && is_spam?(env, current_user, text) + create_spam_log(project, current_user, attrs) + render_api_error!({ error: 'Spam detected' }, 400) + end + + issue = ::Issues::CreateService.new(project, current_user, attrs).execute if issue.valid? # Find or create labels and attach to issue. Labels are valid because diff --git a/lib/gitlab/akismet_helper.rb b/lib/gitlab/akismet_helper.rb new file mode 100644 index 0000000000..71f525309f --- /dev/null +++ b/lib/gitlab/akismet_helper.rb @@ -0,0 +1,39 @@ +module Gitlab + module AkismetHelper + def akismet_enabled? + current_application_settings.akismet_enabled + end + + def akismet_client + ::Akismet::Client.new(current_application_settings.akismet_api_key, + Gitlab.config.gitlab.url) + end + + def check_for_spam?(project, user) + akismet_enabled? && !project.team.member?(user) + end + + def is_spam?(environment, user, text) + client = akismet_client + ip_address = environment['REMOTE_ADDR'] + user_agent = environment['HTTP_USER_AGENT'] + + params = { + type: 'comment', + text: text, + created_at: DateTime.now, + author: user.name, + author_email: user.email, + referrer: environment['HTTP_REFERER'], + } + + begin + is_spam, is_blatant = client.check(ip_address, user_agent, params) + is_spam || is_blatant + rescue => e + Rails.logger.error("Unable to connect to Akismet: #{e}, skipping check") + false + end + end + end +end diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb index a6b2f14521..8531c7e87e 100644 --- a/lib/gitlab/current_settings.rb +++ b/lib/gitlab/current_settings.rb @@ -34,7 +34,8 @@ module Gitlab shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'], max_artifacts_size: Settings.artifacts['max_size'], require_two_factor_authentication: false, - two_factor_grace_period: 48 + two_factor_grace_period: 48, + akismet_enabled: false ) end diff --git a/spec/controllers/admin/spam_logs_controller_spec.rb b/spec/controllers/admin/spam_logs_controller_spec.rb new file mode 100644 index 0000000000..2486298fc7 --- /dev/null +++ b/spec/controllers/admin/spam_logs_controller_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper' + +describe Admin::SpamLogsController do + let(:admin) { create(:admin) } + let(:spam_log) { create(:spam_log, user: admin) } + + before do + sign_in(admin) + end + + describe '#index' do + it 'lists all spam logs' do + get :index + expect(response.status).to eq(200) + end + end + + describe '#destroy' do + it 'destroys just spam log' do + user = spam_log.user + delete :destroy, id: spam_log.id + + expect(SpamLog.all.count).to eq(0) + expect(User.find(user.id)).to be_truthy + expect(response.status).to eq(302) + end + + it 'destroys user and his spam logs' do + user = spam_log.user + delete :destroy, id: spam_log.id, remove_user: true + + expect(SpamLog.all.count).to eq(0) + expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound) + expect(response.status).to eq(302) + end + + it 'destroys user and his spam logs with JSON format' do + user = spam_log.user + delete :destroy, id: spam_log.id, remove_user: true, format: :json + + expect(SpamLog.all.count).to eq(0) + expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound) + expect(JSON.parse(response.body)).to eq({}) + expect(response.status).to eq(200) + end + end +end diff --git a/spec/factories/spam_logs.rb b/spec/factories/spam_logs.rb new file mode 100644 index 0000000000..9e8686d73c --- /dev/null +++ b/spec/factories/spam_logs.rb @@ -0,0 +1,7 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :spam_log do + user + end +end diff --git a/spec/lib/gitlab/akismet_helper_spec.rb b/spec/lib/gitlab/akismet_helper_spec.rb new file mode 100644 index 0000000000..9858935180 --- /dev/null +++ b/spec/lib/gitlab/akismet_helper_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe Gitlab::AkismetHelper, type: :helper do + let(:project) { create(:project) } + let(:user) { create(:user) } + + before do + allow(Gitlab.config.gitlab).to receive(:url).and_return(Settings.send(:build_gitlab_url)) + current_application_settings.akismet_enabled = true + current_application_settings.akismet_api_key = '12345' + end + + describe '#check_for_spam?' do + it 'returns true for non-member' do + expect(helper.check_for_spam?(project, user)).to eq(true) + end + + it 'returns false for member' do + project.team << [user, :guest] + expect(helper.check_for_spam?(project, user)).to eq(false) + end + end + + describe '#is_spam?' do + it 'returns true for spam' do + environment = { + 'REMOTE_ADDR' => '127.0.0.1', + 'HTTP_USER_AGENT' => 'Test User Agent' + } + + allow_any_instance_of(::Akismet::Client).to receive(:check).and_return([true, true]) + expect(helper.is_spam?(environment, user, 'Is this spam?')).to eq(true) + end + end +end diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 5e65ad18c0..2e50344c14 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -241,6 +241,28 @@ describe API::API, api: true do end end + describe 'POST /projects/:id/issues with spam filtering' do + before do + Grape::Endpoint.before_each do |endpoint| + allow(endpoint).to receive(:check_for_spam?).and_return(true) + allow(endpoint).to receive(:is_spam?).and_return(true) + end + end + + it "should create a new project issue" do + post api("/projects/#{project.id}/issues", user), + title: 'new issue', labels: 'label, label2' + expect(response.status).to eq(400) + expect(json_response['message']).to eq({ "error" => "Spam detected" }) + spam_logs = SpamLog.all + expect(spam_logs.count).to eq(1) + expect(spam_logs[0].title).to eq('new issue') + expect(spam_logs[0].user).to eq(user) + expect(spam_logs[0].noteable_type).to eq('Issue') + expect(spam_logs[0].project_id).to eq(project.id) + end + end + describe "PUT /projects/:id/issues/:issue_id to update only title" do it "should update a project issue" do put api("/projects/#{project.id}/issues/#{issue.id}", user), From 64c9768bd6916edfc1e43907ca5e976524b8d51b Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 16:59:23 -0200 Subject: [PATCH 47/89] Use truncate helper on spam logs list --- app/models/spam_log.rb | 8 ------- app/views/admin/spam_logs/_spam_log.html.haml | 2 +- features/steps/admin/spam_logs.rb | 22 ++++++++++++++----- spec/factories/spam_logs.rb | 4 ++++ 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/app/models/spam_log.rb b/app/models/spam_log.rb index 132c5713e0..b7b32b478a 100644 --- a/app/models/spam_log.rb +++ b/app/models/spam_log.rb @@ -2,12 +2,4 @@ class SpamLog < ActiveRecord::Base belongs_to :user validates :user, presence: true - - def truncated_description - if description.present? && description.length > 100 - return description[0..100] + "..." - end - - description - end end diff --git a/app/views/admin/spam_logs/_spam_log.html.haml b/app/views/admin/spam_logs/_spam_log.html.haml index 1c793bbf73..9f9f1d7589 100644 --- a/app/views/admin/spam_logs/_spam_log.html.haml +++ b/app/views/admin/spam_logs/_spam_log.html.haml @@ -16,7 +16,7 @@ %td = spam_log.title %td - = spam_log.truncated_description + = truncate(spam_log.description, length: 100) %td - if user = link_to 'Remove user', admin_spam_log_path(spam_log, remove_user: true), diff --git a/features/steps/admin/spam_logs.rb b/features/steps/admin/spam_logs.rb index 79d18b036b..ad825fd414 100644 --- a/features/steps/admin/spam_logs.rb +++ b/features/steps/admin/spam_logs.rb @@ -4,15 +4,25 @@ class Spinach::Features::AdminSpamLogs < Spinach::FeatureSteps include SharedAdmin step 'I should see list of spam logs' do - page.should have_content("Spam Logs") - spam_log = SpamLog.first - page.should have_content spam_log.title - page.should have_content spam_log.description - page.should have_link("Remove user") - page.should have_link("Block user") + expect(page).to have_content('Spam Logs') + expect(page).to have_content spam_log.source_ip + expect(page).to have_content spam_log.noteable_type + expect(page).to have_content 'N' + expect(page).to have_content spam_log.title + expect(page).to have_content truncate(spam_log.description) + expect(page).to have_link('Remove user') + expect(page).to have_link('Block user') end step 'spam logs exist' do create(:spam_log) end + + def spam_log + @spam_log ||= SpamLog.first + end + + def truncate(description) + "#{spam_log.description[0...97]}..." + end end diff --git a/spec/factories/spam_logs.rb b/spec/factories/spam_logs.rb index 9e8686d73c..d90e5d6bf2 100644 --- a/spec/factories/spam_logs.rb +++ b/spec/factories/spam_logs.rb @@ -3,5 +3,9 @@ FactoryGirl.define do factory :spam_log do user + source_ip { FFaker::Internet.ip_v4_address } + noteable_type 'Issue' + title { FFaker::Lorem.sentence } + description { FFaker::Lorem.paragraph(5) } end end From 80d0a2a6d8dccbb9888f9cd4dc3c3e7e208817e6 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 17:01:56 -0200 Subject: [PATCH 48/89] Add model spec for SpamLog --- spec/models/spam_log_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 spec/models/spam_log_spec.rb diff --git a/spec/models/spam_log_spec.rb b/spec/models/spam_log_spec.rb new file mode 100644 index 0000000000..076f3e44c7 --- /dev/null +++ b/spec/models/spam_log_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe SpamLog, models: true do + describe 'associations' do + it { is_expected.to belong_to(:user) } + end + + describe 'validations' do + it { is_expected.to validate_presence_of(:user) } + end +end From e38a1fc83ee7a9fb04fe370204f0094723890f00 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 17:55:33 -0200 Subject: [PATCH 49/89] Fix typo on User model --- app/models/user.rb | 2 +- spec/models/user_spec.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 63c895683f..234c1cd89f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -138,7 +138,7 @@ class User < ActiveRecord::Base has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy has_one :abuse_report, dependent: :destroy - has_many :spam_log, dependent: :destroy + has_many :spam_logs, dependent: :destroy has_many :builds, dependent: :nullify, class_name: 'Ci::Build' diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 0bef68e288..cee051f573 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -91,6 +91,7 @@ describe User, models: true do it { is_expected.to have_many(:assigned_merge_requests).dependent(:destroy) } it { is_expected.to have_many(:identities).dependent(:destroy) } it { is_expected.to have_one(:abuse_report) } + it { is_expected.to have_many(:spam_logs).dependent(:destroy) } end describe 'validations' do From 62cad887ea695d40afee894089f894ee398cf98a Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 18:03:01 -0200 Subject: [PATCH 50/89] Use time_ago_with_tooltip on spam logs list --- app/views/admin/spam_logs/_spam_log.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/spam_logs/_spam_log.html.haml b/app/views/admin/spam_logs/_spam_log.html.haml index 9f9f1d7589..51e94acce2 100644 --- a/app/views/admin/spam_logs/_spam_log.html.haml +++ b/app/views/admin/spam_logs/_spam_log.html.haml @@ -1,7 +1,7 @@ - user = spam_log.user %tr %td - = spam_log.created_at.to_s(:short) + = time_ago_with_tooltip(spam_log.created_at) %td - if user = link_to user.name, user From a2bbf004779db402e67a918db893c166502f5050 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 18:08:20 -0200 Subject: [PATCH 51/89] Refactor spam filtering on issues API --- lib/api/issues.rb | 15 ++++++++------- spec/requests/api/issues_spec.rb | 11 ++++++++--- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/api/issues.rb b/lib/api/issues.rb index cdadd13c13..252744515d 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -23,11 +23,13 @@ module API end def create_spam_log(project, current_user, attrs) - params = attrs.dup - params[:source_ip] = env['REMOTE_ADDR'] - params[:user_agent] = env['HTTP_USER_AGENT'] - params[:noteable_type] = 'Issue' - params[:via_api] = true + params = attrs.merge({ + source_ip: env['REMOTE_ADDR'], + user_agent: env['HTTP_USER_AGENT'], + noteable_type: 'Issue', + via_api: true + }) + ::CreateSpamLogService.new(project, current_user, params).execute end end @@ -126,8 +128,7 @@ module API end project = user_project - text = attrs[:title] - text += "\n#{attrs[:description]}" if attrs[:description].present? + text = [attrs[:title], attrs[:description]].reject(&:blank?).join("\n") if check_for_spam?(project, current_user) && is_spam?(env, current_user, text) create_spam_log(project, current_user, attrs) diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 2e50344c14..dcf1b394a3 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -249,14 +249,19 @@ describe API::API, api: true do end end - it "should create a new project issue" do - post api("/projects/#{project.id}/issues", user), - title: 'new issue', labels: 'label, label2' + it "should not create a new project issue" do + expect { + post api("/projects/#{project.id}/issues", user), + title: 'new issue', description: 'content here', labels: 'label, label2' + }.not_to change(Issue, :count) + expect(response.status).to eq(400) expect(json_response['message']).to eq({ "error" => "Spam detected" }) + spam_logs = SpamLog.all expect(spam_logs.count).to eq(1) expect(spam_logs[0].title).to eq('new issue') + expect(spam_logs[0].description).to eq('content here') expect(spam_logs[0].user).to eq(user) expect(spam_logs[0].noteable_type).to eq('Issue') expect(spam_logs[0].project_id).to eq(project.id) From 718b1dddfe8d7422e8de8b2fbbd8357fc1c3b5e4 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 19:20:01 -0200 Subject: [PATCH 52/89] Refactor Admin::SpamLogsController to block user before destroying --- app/controllers/admin/spam_logs_controller.rb | 30 +++---------- app/models/spam_log.rb | 5 +++ app/views/admin/spam_logs/_spam_log.html.haml | 8 ++-- app/views/admin/spam_logs/index.html.haml | 2 +- .../admin/spam_logs_controller_spec.rb | 43 ++++++++----------- spec/models/spam_log_spec.rb | 14 ++++++ 6 files changed, 50 insertions(+), 52 deletions(-) diff --git a/app/controllers/admin/spam_logs_controller.rb b/app/controllers/admin/spam_logs_controller.rb index 69f94dd3ba..377e9741e5 100644 --- a/app/controllers/admin/spam_logs_controller.rb +++ b/app/controllers/admin/spam_logs_controller.rb @@ -1,33 +1,17 @@ class Admin::SpamLogsController < Admin::ApplicationController - before_action :set_spam_log, only: [:destroy] - def index - @spam_logs = SpamLog.order(created_at: :desc).page(params[:page]) + @spam_logs = SpamLog.order(id: :desc).page(params[:page]) end def destroy - @spam_log.destroy - message = 'Spam log was successfully destroyed.' + spam_log = SpamLog.find(params[:id]) if params[:remove_user] - username = @spam_log.user.username - @spam_log.user.destroy - message = "User #{username} was successfully destroyed." + spam_log.remove_user + redirect_to admin_spam_logs_path, notice: "User #{spam_log.user.username} was successfully removed." + else + spam_log.destroy + render nothing: true end - - respond_to do |format| - format.json { render json: '{}' } - format.html { redirect_to admin_spam_logs_path, notice: message } - end - end - - private - - def set_spam_log - @spam_log = SpamLog.find(params[:id]) - end - - def spam_log_params - params[:spam_log] end end diff --git a/app/models/spam_log.rb b/app/models/spam_log.rb index b7b32b478a..12df68ef83 100644 --- a/app/models/spam_log.rb +++ b/app/models/spam_log.rb @@ -2,4 +2,9 @@ class SpamLog < ActiveRecord::Base belongs_to :user validates :user, presence: true + + def remove_user + user.block + user.destroy + end end diff --git a/app/views/admin/spam_logs/_spam_log.html.haml b/app/views/admin/spam_logs/_spam_log.html.haml index 51e94acce2..8aea67f449 100644 --- a/app/views/admin/spam_logs/_spam_log.html.haml +++ b/app/views/admin/spam_logs/_spam_log.html.haml @@ -4,13 +4,15 @@ = time_ago_with_tooltip(spam_log.created_at) %td - if user - = link_to user.name, user + = link_to user.name, [:admin, user] + .light.small + Joined #{time_ago_with_tooltip(user.created_at)} - else (removed) %td = spam_log.source_ip %td - = spam_log.via_api ? 'Y' : 'N' + = spam_log.via_api? ? 'Y' : 'N' %td = spam_log.noteable_type %td @@ -27,4 +29,4 @@ - else .btn.btn-xs.disabled Already Blocked - = link_to 'Remove log', [:admin, spam_log, format: :json], remote: true, method: :delete, class: "btn btn-xs btn-close js-remove-tr" + = link_to 'Remove log', [:admin, spam_log], remote: true, method: :delete, class: "btn btn-xs btn-close js-remove-tr" diff --git a/app/views/admin/spam_logs/index.html.haml b/app/views/admin/spam_logs/index.html.haml index 439468e572..0fdd5bd996 100644 --- a/app/views/admin/spam_logs/index.html.haml +++ b/app/views/admin/spam_logs/index.html.haml @@ -9,7 +9,7 @@ %th Date %th User %th Source IP - %th Via API? + %th API? %th Type %th Title %th Description diff --git a/spec/controllers/admin/spam_logs_controller_spec.rb b/spec/controllers/admin/spam_logs_controller_spec.rb index 2486298fc7..6beebc362e 100644 --- a/spec/controllers/admin/spam_logs_controller_spec.rb +++ b/spec/controllers/admin/spam_logs_controller_spec.rb @@ -1,8 +1,10 @@ require 'spec_helper' describe Admin::SpamLogsController do - let(:admin) { create(:admin) } - let(:spam_log) { create(:spam_log, user: admin) } + let(:admin) { create(:admin) } + let(:user) { create(:user) } + let!(:first_spam) { create(:spam_log, user: user) } + let!(:second_spam) { create(:spam_log, user: user) } before do sign_in(admin) @@ -11,37 +13,28 @@ describe Admin::SpamLogsController do describe '#index' do it 'lists all spam logs' do get :index + expect(response.status).to eq(200) end end describe '#destroy' do - it 'destroys just spam log' do - user = spam_log.user - delete :destroy, id: spam_log.id + it 'removes only the spam log when removing log' do + expect { + delete :destroy, id: first_spam.id + }.to change { SpamLog.count }.by(-1) - expect(SpamLog.all.count).to eq(0) expect(User.find(user.id)).to be_truthy - expect(response.status).to eq(302) - end - - it 'destroys user and his spam logs' do - user = spam_log.user - delete :destroy, id: spam_log.id, remove_user: true - - expect(SpamLog.all.count).to eq(0) - expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound) - expect(response.status).to eq(302) - end - - it 'destroys user and his spam logs with JSON format' do - user = spam_log.user - delete :destroy, id: spam_log.id, remove_user: true, format: :json - - expect(SpamLog.all.count).to eq(0) - expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound) - expect(JSON.parse(response.body)).to eq({}) expect(response.status).to eq(200) end + + it 'removes user and his spam logs when removing the user' do + delete :destroy, id: first_spam.id, remove_user: true + + expect(flash[:notice]).to eq "User #{user.username} was successfully removed." + expect(response.status).to eq(302) + expect(SpamLog.count).to eq(0) + expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound) + end end end diff --git a/spec/models/spam_log_spec.rb b/spec/models/spam_log_spec.rb index 076f3e44c7..c4ec7625cb 100644 --- a/spec/models/spam_log_spec.rb +++ b/spec/models/spam_log_spec.rb @@ -8,4 +8,18 @@ describe SpamLog, models: true do describe 'validations' do it { is_expected.to validate_presence_of(:user) } end + + describe '#remove_user' do + it 'blocks the user' do + spam_log = build(:spam_log) + + expect { spam_log.remove_user }.to change { spam_log.user.blocked? }.to(true) + end + + it 'removes the user' do + spam_log = build(:spam_log) + + expect { spam_log.remove_user }.to change { User.count }.by(-1) + end + end end From eefc46e0d5310cce5b5a64c1b982d5348d465f83 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 19:51:52 -0200 Subject: [PATCH 53/89] Fix rubocop offenses --- .../controllers/admin/spam_logs_controller_spec.rb | 5 +---- spec/requests/api/issues_spec.rb | 14 +++++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/spec/controllers/admin/spam_logs_controller_spec.rb b/spec/controllers/admin/spam_logs_controller_spec.rb index 6beebc362e..b51b303a71 100644 --- a/spec/controllers/admin/spam_logs_controller_spec.rb +++ b/spec/controllers/admin/spam_logs_controller_spec.rb @@ -20,10 +20,7 @@ describe Admin::SpamLogsController do describe '#destroy' do it 'removes only the spam log when removing log' do - expect { - delete :destroy, id: first_spam.id - }.to change { SpamLog.count }.by(-1) - + expect { delete :destroy, id: first_spam.id }.to change { SpamLog.count }.by(-1) expect(User.find(user.id)).to be_truthy expect(response.status).to eq(200) end diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index dcf1b394a3..4443036d98 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -249,12 +249,16 @@ describe API::API, api: true do end end - it "should not create a new project issue" do - expect { - post api("/projects/#{project.id}/issues", user), - title: 'new issue', description: 'content here', labels: 'label, label2' - }.not_to change(Issue, :count) + let(:params) do + { + title: 'new issue', + description: 'content here', + labels: 'label, label2' + } + end + it "should not create a new project issue" do + expect { post api("/projects/#{project.id}/issues", user), params }.not_to change(Issue, :count) expect(response.status).to eq(400) expect(json_response['message']).to eq({ "error" => "Spam detected" }) From 07384aa00d8a8759cdb29ba51ae32a6032ba2571 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 1 Feb 2016 22:05:56 -0200 Subject: [PATCH 54/89] Memoize Akismet client initialization on AkismetHelper --- lib/gitlab/akismet_helper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/akismet_helper.rb b/lib/gitlab/akismet_helper.rb index 71f525309f..b366c89889 100644 --- a/lib/gitlab/akismet_helper.rb +++ b/lib/gitlab/akismet_helper.rb @@ -5,8 +5,8 @@ module Gitlab end def akismet_client - ::Akismet::Client.new(current_application_settings.akismet_api_key, - Gitlab.config.gitlab.url) + @akismet_client ||= ::Akismet::Client.new(current_application_settings.akismet_api_key, + Gitlab.config.gitlab.url) end def check_for_spam?(project, user) From 0ea5d764f2ad8d94adfca36b20ce92e67af81e36 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 1 Feb 2016 22:25:00 -0200 Subject: [PATCH 55/89] Hide the link for spam logs if the Askimet is disabled --- app/helpers/application_settings_helper.rb | 4 ++++ app/views/layouts/nav/_admin.html.haml | 13 +++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 7d6b58ee21..23693629a4 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -23,6 +23,10 @@ module ApplicationSettingsHelper current_application_settings.user_oauth_applications end + def askimet_enabled? + current_application_settings.akismet_enabled? + end + # Return a group of checkboxes that use Bootstrap's button plugin for a # toggle button effect. def restricted_level_checkboxes(help_block_id) diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index 8dc2058742..5f8212ea26 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -82,12 +82,13 @@ Abuse Reports %span.count= number_with_delimiter(AbuseReport.count(:all)) - = nav_link(controller: :spam_logs) do - = link_to admin_spam_logs_path, title: "Spam Logs" do - = icon('exclamation-triangle fw') - %span - Spam Logs - %span.count= number_with_delimiter(SpamLog.count(:all)) + - if askimet_enabled? + = nav_link(controller: :spam_logs) do + = link_to admin_spam_logs_path, title: "Spam Logs" do + = icon('exclamation-triangle fw') + %span + Spam Logs + %span.count= number_with_delimiter(SpamLog.count(:all)) = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do = link_to admin_application_settings_path, title: 'Settings' do From dffacbb12c0abd4edf677aed2d9e201b41fd2dae Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 1 Feb 2016 22:28:33 -0200 Subject: [PATCH 56/89] Update CHANGELOG --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 1be1f7374d..187ab00005 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -22,6 +22,7 @@ v 8.5.0 (unreleased) - Deprecate API "merge_request/:merge_request_id/comments". Use "merge_requests/:merge_request_id/notes" instead - Deprecate API "merge_request/:merge_request_id/...". Use "merge_requests/:merge_request_id/..." instead - Mark inline difference between old and new paths when a file is renamed + - Support Akismet spam checking for creation of issues via API (Stan Hu) v 8.4.3 - Increase lfs_objects size column to 8-byte integer to allow files larger @@ -74,7 +75,6 @@ v 8.4.0 - Don't notify users twice if they are both project watchers and subscribers (Stan Hu) - Remove gray background from layout in UI - Fix signup for OAuth providers that don't provide a name - - Support Akismet spam checking for creation of issues via API (Stan Hu) - Implement new UI for group page - Implement search inside emoji picker - Let the CI runner know about builds that this build depends on From 0a4db90d36870211df2dc1e606b01602666706c8 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 14:35:09 +0100 Subject: [PATCH 57/89] Use begin/end instead of defined? --- app/models/ci/commit.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 96786ac457..ecbd2078b1 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -205,11 +205,11 @@ module Ci end def ci_yaml_file - return @ci_yaml_file if defined?(@ci_yaml_file) - - blob = project.repository.blob_at(sha, '.gitlab-ci.yml') - blob.load_all_data!(project.repository) - @ci_yaml_file = blob.data + @ci_yaml_file ||= begin + blob = project.repository.blob_at(sha, '.gitlab-ci.yml') + blob.load_all_data!(project.repository) + blob.data + end rescue nil end From e08aa3df905f09f1c964fb056cba922a1d6eaa85 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 15:04:50 +0100 Subject: [PATCH 58/89] Use gitlab_git 8.0.0 --- Gemfile | 2 +- Gemfile.lock | 20 +++++++------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/Gemfile b/Gemfile index 88236146a1..a511b114f9 100644 --- a/Gemfile +++ b/Gemfile @@ -49,7 +49,7 @@ gem "browser", '~> 1.0.0' # Extracting information from a git repository # Provide access to Gitlab::Git library -gem "gitlab_git", git: 'https://gitlab.com/gitlab-org/gitlab_git.git', branch: 'lazy-blob' +gem "gitlab_git", '~> 8.0.0' # LDAP Auth # GitLab fork with several improvements to original library. For full list of changes diff --git a/Gemfile.lock b/Gemfile.lock index 9aacbced99..211cb9a42a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,14 +1,3 @@ -GIT - remote: https://gitlab.com/gitlab-org/gitlab_git.git - revision: 57160e1cbcf4c03e68aa881dfa8e2f55c37a3ee6 - branch: lazy-blob - specs: - gitlab_git (7.2.24) - activesupport (~> 4.0) - charlock_holmes (~> 0.7.3) - github-linguist (~> 4.7.0) - rugged (~> 0.23.3) - GEM remote: https://rubygems.org/ specs: @@ -350,7 +339,7 @@ GEM json get_process_mem (0.2.0) gherkin-ruby (0.3.2) - github-linguist (4.7.4) + github-linguist (4.7.3) charlock_holmes (~> 0.7.3) escape_utils (~> 1.1.0) mime-types (>= 1.19) @@ -367,6 +356,11 @@ GEM posix-spawn (~> 0.3) gitlab_emoji (0.2.0) gemojione (~> 2.1) + gitlab_git (8.0.0) + activesupport (~> 4.0) + charlock_holmes (~> 0.7.3) + github-linguist (~> 4.7.0) + rugged (~> 0.23.3) gitlab_meta (7.0) gitlab_omniauth-ldap (1.2.1) net-ldap (~> 0.9) @@ -940,7 +934,7 @@ DEPENDENCIES github-markup (~> 1.3.1) gitlab-flowdock-git-hook (~> 1.0.1) gitlab_emoji (~> 0.2.0) - gitlab_git! + gitlab_git (~> 8.0.0) gitlab_meta (= 7.0) gitlab_omniauth-ldap (~> 1.2.1) gollum-lib (~> 4.1.0) From b67f8eee0d2810be4a010c5e968e1848b4ca3c88 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 15:06:14 +0100 Subject: [PATCH 59/89] Use @repository --- app/controllers/projects/avatars_controller.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index bc40e60103..f7e6bb3444 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -2,11 +2,10 @@ class Projects::AvatarsController < Projects::ApplicationController before_action :project def show - repository = @project.repository - @blob = repository.blob_at_branch('master', @project.avatar_in_git) + @blob = @repository.blob_at_branch('master', @project.avatar_in_git) if @blob headers['X-Content-Type-Options'] = 'nosniff' - headers.store(*Gitlab::Workhorse.send_git_blob(repository, @blob)) + headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) headers['Content-Disposition'] = 'inline' headers['Content-Type'] = @blob.content_type head :ok # 'render nothing: true' messes up the Content-Type From c41a8be8d266ceefac307939a2acfd103260fb29 Mon Sep 17 00:00:00 2001 From: Michi302 Date: Wed, 6 Jan 2016 20:11:50 +0100 Subject: [PATCH 60/89] Fix add_pagination_headers to keep request parameters in Link header --- CHANGELOG | 1 + lib/api/helpers.rb | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7a70516173..f207e0c531 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,7 @@ v 8.5.0 (unreleased) - Update the ExternalIssue regex pattern (Blake Hitchcock) - Optimized performance of finding issues to be closed by a merge request - Revert "Add IP check against DNSBLs at account sign-up" + - Fix API to keep request parameters in Link header (Michael Potthoff) - Deprecate API "merge_request/:merge_request_id/comments". Use "merge_requests/:merge_request_id/notes" instead - Deprecate API "merge_request/:merge_request_id/...". Use "merge_requests/:merge_request_id/..." instead - Mark inline difference between old and new paths when a file is renamed diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 9dacf7c1e8..a72044e805 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -30,7 +30,7 @@ module API end def sudo_identifier() - identifier ||= params[SUDO_PARAM] ||= env[SUDO_HEADER] + identifier ||= params[SUDO_PARAM] || env[SUDO_HEADER] # Regex for integers if !!(identifier =~ /^[0-9]+$/) @@ -344,12 +344,22 @@ module API def pagination_links(paginated_data) request_url = request.url.split('?').first + request_params = params.clone + request_params[:per_page] = paginated_data.limit_value links = [] - links << %(<#{request_url}?page=#{paginated_data.current_page - 1}&per_page=#{paginated_data.limit_value}>; rel="prev") unless paginated_data.first_page? - links << %(<#{request_url}?page=#{paginated_data.current_page + 1}&per_page=#{paginated_data.limit_value}>; rel="next") unless paginated_data.last_page? - links << %(<#{request_url}?page=1&per_page=#{paginated_data.limit_value}>; rel="first") - links << %(<#{request_url}?page=#{paginated_data.total_pages}&per_page=#{paginated_data.limit_value}>; rel="last") + + request_params[:page] = paginated_data.current_page - 1 + links << %(<#{request_url}?#{request_params.to_query}>; rel="prev") unless paginated_data.first_page? + + request_params[:page] = paginated_data.current_page + 1 + links << %(<#{request_url}?#{request_params.to_query}>; rel="next") unless paginated_data.last_page? + + request_params[:page] = 1 + links << %(<#{request_url}?#{request_params.to_query}>; rel="first") + + request_params[:page] = paginated_data.total_pages + links << %(<#{request_url}?#{request_params.to_query}>; rel="last") links.join(', ') end From 070a3079fc9115ec564bc48f6b4deec5cabd901d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 2 Feb 2016 14:34:46 +0100 Subject: [PATCH 61/89] Add a spec for the API pagination Link header --- spec/requests/api/issues_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 5e65ad18c0..410e684ee3 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -46,10 +46,10 @@ describe API::API, api: true do expect(json_response.first['title']).to eq(issue.title) end - it "should add pagination headers" do - get api("/issues?per_page=3", user) + it "should add pagination headers and keep query params" do + get api("/issues?state=closed&per_page=3", user) expect(response.headers['Link']).to eq( - '; rel="first", ; rel="last"' + '; rel="first", ; rel="last"' % [user.private_token, user.private_token] ) end From d716905743352de34bca8441706eef776f1cd6ce Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 16:00:13 +0100 Subject: [PATCH 62/89] Use gitlab-workhorse 0.6.3 --- GITLAB_WORKHORSE_VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index b616048743..844f6a91ac 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -0.6.2 +0.6.3 From ea41d3607769b2b726a25d50ea23675bc5936227 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 16:01:20 +0100 Subject: [PATCH 63/89] Use gitlab-workhorse 0.6.3 in installation guide --- doc/install/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 2cc2dbef41..a2c23bd52e 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -355,7 +355,7 @@ GitLab Shell is an SSH access and repository management software developed speci cd /home/git sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git cd gitlab-workhorse - sudo -u git -H git checkout 0.6.2 + sudo -u git -H git checkout 0.6.3 sudo -u git -H make ### Initialize Database and Activate Advanced Features From a12ac9c060018071d75c7b1e9d9ee3b90cb4d792 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 2 Feb 2016 14:50:14 -0500 Subject: [PATCH 64/89] Update CHANGELOG [ci skip] --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7a9b51cf33..3469a1e026 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -32,6 +32,9 @@ v 8.4.3 - Fix highlighting in blame view - Update sentry-raven gem to prevent "Not a git repository" console output when running certain commands + - Add instrumentation to additional Gitlab::Git and Rugged methods for + performance monitoring + - Allow autosize textareas to also be manually resized v 8.4.2 - Bump required gitlab-workhorse version to bring in a fix for missing From acea6e1c507cf35123a8fe87ca708683719f4820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20Bl=C3=A4ttermann?= Date: Tue, 26 Jan 2016 23:53:36 +0000 Subject: [PATCH 65/89] Documentation cleanup of artifacts section in Gitlab CI Readme - Added notice about build artifacts not beeing collected on failed builds. - Removed "introduced in 0.7.0" for artifacts section. - Made windows notice more precise --- doc/ci/yaml/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 4d280297db..194c8171bb 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -393,8 +393,12 @@ The above script will: ### artifacts -_**Note:** Introduced in GitLab Runner v0.7.0. Also, the Windows shell executor - does not currently support artifact uploads._ +_**Note:** Introduced in GitLab Runner v0.7.0 for non-Windows platforms._ + +_**Note:** Limited Windows support was added in GitLab Runner v.1.0.0. +Currently not all executors are supported._ + +_**Note:** Build artifacts are only collected for successful builds._ `artifacts` is used to specify list of files and directories which should be attached to build after success. Below are some examples. From cbd550cfa68581127e344f31d8d7c624bdc52cbb Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 3 Feb 2016 13:18:37 +0200 Subject: [PATCH 66/89] Refactor OAuth provider documentation [ci skip] --- .../img/oauth_provider_admin_application.png | Bin 55533 -> 40579 bytes .../img/oauth_provider_application_form.png | Bin 25075 -> 27974 bytes .../oauth_provider_application_id_secret.png | Bin 0 -> 33901 bytes .../oauth_provider_authorized_application.png | Bin 17260 -> 32225 bytes .../oauth_provider_user_wide_applications.png | Bin 46238 -> 40632 bytes doc/integration/oauth_provider.md | 89 +++++++++++++----- 6 files changed, 67 insertions(+), 22 deletions(-) create mode 100644 doc/integration/img/oauth_provider_application_id_secret.png diff --git a/doc/integration/img/oauth_provider_admin_application.png b/doc/integration/img/oauth_provider_admin_application.png index a5f34512aa85236ac9ecc7d70129d8a3a3f1a71b..a2d8e14c1205d751ced539d5c269b391ce01588e 100644 GIT binary patch literal 40579 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 literal 55533 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 z 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 diff --git a/doc/integration/img/oauth_provider_application_id_secret.png b/doc/integration/img/oauth_provider_application_id_secret.png new file mode 100644 index 0000000000000000000000000000000000000000..6d68df001af5f63476c313a0a52c936ade885e85 GIT binary patch literal 33901 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 Pw`g3^Q7=}#{rG3~n{&?ZlzsNz=e`2#-e*0* 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�ESgQ_0+a<0)oovys>U_GGow>Di^WtjuSfrXe^p<&* z+Rth8bqk3NpwJi?OmB~aw?_-S#AW?mi#xf&*CQOps9QnV`vmS?_vad<^#>`X^6H_x}R``SaEuo5C1F z7^gjOBX=zh%gM}3#&>-oOXLzfYz$rU9FWgK6Ow%wPrCqAzlO?7#CgJ&XQ{Bi(t(Ned@wljby z-SwWWT`?gxv6Hc`p7kitH)Vwy z_ir0ZE?gUbA!W<0J%2sYn`>^e-5m4}cS?%TcByV%f=xHB^8=PfdzB%3N+Y|hYM~P< z4WJE0eT-|w8TWzjM>R^1zYCSNB@(z4H|N{h+c`X9xl3gUxwxL-?gx49JN)9p)JKDX zApY8@?9Dp6%hgYDF@ujWa%3vPD>~M!;rOQDesaCEY~$^Z(6R1c(V)D!`lFfN>&BVb ztApxWS>2*bhNEosxV$v+doh!Ah9c^Z)?xeXHaHu0KuwF}k-7>QgW44r3k$4yP^(=e za3u38O2Ful@`& z&!NIYz~IJ7BPaDnc77@mkHMsmVIrjJR(Y-*eM%Io@zglAVlh*vGLUr)3aBvHZX;8q zl<}whJG_~Qy(soLt|pPyDS3nTrC2Pdy|d~iE}O zrw1F`cK)qPTJL)gLid!IszB*5Vfk8V2;1oaNz#~f^X{q<#NX-pAWbf(b?RuTx^aQ& zzOZnL{4S-T0dJfobLM9i6HQFYHUW*9$KIAayP-i3FihYhMIMJkV=-q+A0c+)QN>NK zuO`d!Tep5_``%^ZFl4RWodnudADn-&k<7iy2h>u&%)bmPyk^eNnRFKV3Dx~aw#0-= zYqOHZxC?U^EG{lS;MR7zIngB~Ok=OI2%}@Fiqg9wJ0Hyum}^Ert|2GXh)h!VDD3O& zDQchNK64^*-N@KHtxP3+5RsHSQ^`}!f`Z)NebBU{EHA|i*`JTvI;h3q)_vYRe`yv| z>F91kGFU{=qpeI?rE|IbruO6+-6>jS{C0AQzWMsf-u*)F2uL=!w{&R(BB%6T7dI{> z+&QvWbayo37h0(k$D;l_OIs~Lq1DKvKu4sZDV0tckU3I}c)B`V7#kZSz6Ys?jH088 zeMNKkxM`_XNm?P%6+FkS0dTn-v8=QRY9V!R4{1oo8ENx7x>;uC)NrWVUDo;&K7N7X zEP!y)+UDcslLF_V3&xGmQq5q3(B)3G`aZi&oN1wo;O6UrrMiFk_bcf(n-p<_j|7~o zrsLVTId8UFwmo>j4F9bKHePazrimdZ^m;W5fhT@+0=CXll*oW*k9 zQ~ihbWT$hDVe>h?$^S& zFM@|guC`roUWZj0w|e8(aOqvoT5kh}#m}ij$Au`zHEwpZ!h&T-Xp-30jpl0$y;Mw> ztsgCp41wfKXebMuocD1eyQLizhchWmN$LN{sbMF7#G4-7()81E%gXJ=_Fi6EZuTBb zu$C(c)HCensT@+#(jo|&Y4N-d$LDZbYH*B0U|PZ0Vi~bg^HgHtI|ld?A!nwrV-{DUsn^Pp7WC_4&!g;eK}fjp$v% z_bs>A*8D;-DV~M9W1nIkl`mS2?7WTLzG$#uQQW;EkDzKgPx~m1K3e)^@A`kM)=N^I zI%$ktYzCwET$3^*3a|!>7MV0|Sc|W?w6v40?cPeOceB0;Y9}XY>eW^}aQgw~m?8cE z4|nv)tE9Buq3c6$Rcr_zm%E!rx6xcI-0ogyuuT&z&CG)1Un4v$t&pPHBg9?DtEO;s zT`e^rKH^$Cti4xFS{nt&t5#d{fpKx-rtj!~n+c5m>$U^;Lh&u5cwY494F2dU^O=(S z>*G9;Bh$ibpmA!(HQZZGMN;$aL3*_2^8z>fcjd7>Izm{BFO{~IUh@P{bC_(EyLAp7 zVHS~ZG%9n8=WN8f>DN=F*h47FPStCt{4f?D(irK9-R2s+)R*z)yWc1LFTgG(3Tu&x zlZ&gOT80VZRV$4!Ffl<%^87J_hU0lwD^2e@i$4+0)KGj1$>5e>H@TYQ2LE3*rw4 zJ1LX`hXQj`J~M~xi_QJA7&itrs>gLSN_!*u(<^U#BXdg5JZoL^UUjv))~yzAp@;R? zr&Vb@E_KZh21*JKz%TZ0gmI~4A?>=Qjjugh_6~`X>XaI7`DjLcm6K(r1Qe7NlbT8f zb4l(rpm#@6DW*X{_N&ib_4+T{_WxSoK%qXqts+8X9DDD;48}(%){kEW0!AkkI!;GP zk?KK21Cg?v3i%>rQLfb*sS_A4Msa>5{J`SG!NI^nH|fH}%#Hm985v<=$qOwQj#!mX zV4Ur3%K zZu_lJZOe%1N$y4>-C+M+Y3(1t;Pm4f{6CcPWWhzLYsREhB$|Uq!9vk#GkR#t1##fr zxm=1`pK#)DYDY)20?RLRZ(qV>CpemjLMPKvJO@up3QJO-hJ7dB2Itqz9_Pxz5i71p zE~R{H&7aIS3q=TfgO;w35i6$2<;E@uZhudQ@)wze_y^>2{fhA|mV&@BL5*!jt;W;Q zH)CAkm8eg&f@LTRYC*#@TwPY0@V5N%F5#Phr(JO{tjAYAO5Q?|<*ekD0BVf5rTd-p zdogS;5eDqP(GR${4w5exfzs$Gw25%dL7|(u@SUdUVN5z-0{;6Alou$7_?yBkGxU2< zgu^9yamAYt6ay7ATroCEg4e$lmwI+z|IHx^3pP_8wI8JWBw3%+O;^GCktG+KDovid)E zMe`iK!dvpl1e`9nXItg^y|A{CYWY0rckkX&#DTYhf&??Y>5=i-V?EZ`wW+m5mm4p$ zSTOT;g4DPZ=Z&(z*oPmBi?<5J&0CEA4{G@(ok$0!v%HwDx8D&C|9sm=6cO17lYn~N zAJ)#4XdW!omJYiQDv+ZFWk&{aaeJ(&4-xW=8a#7b+g@CCDhJ5ax5j-IP5;87o*04@ zmOn1eZw74qsrp}Nsf`xaD55ZbK|@VlQ(a93^8s9&YIb)^LdsE#v;_?E5RoB+2%v&UfS3wqp>ewd(w0O2_{sQLl z)Re&_ssD^YC5YV>O`?K}&SG!b5`IwHo(mJG-Buc4wXUzrY$iN*xh==k+5j zDoQQOq_D?DN87Eo`EG7*Mn^}7V9~(j>r1xN+jOImdb!yD>7T5`uB<%FtZ$;Sd0eI@ z@EYWPoE*t|9K z*{z8y-w7qywYFyiko5M6D!3S0yJ;D>1RKVK>ZSL}E` z8;%bt67>z6b=)6l;VLM_KR+HI%&jKGx8A(kO2S{(Ot_wJQlQoj`Cn%T8{;v1e>U0-`y7GZF+gTxBYi&hgU8NysD5T-A9x^;XihtrPV2&&ek8l zuOa;WZ_1(}fBeq6b*a?dxwqV6qLhqg!H}>V)YQkpVs|}vPBeQwG@aG@nnTR#>WVbB zor;Qyo*wVW;@(q(P8MJ=r}0wMP1H{x$O7eqp4ZIxPou>30u_yh2A{mFI@*6RJG z5P?%fKk=cWtcYkajM)SJgaWM`CYQteA380E!h#vJlFsRvwzXpxTy88q`!l~>Z};Ey zXtGjva&3ei4ICDKEOvVS_cM~ehbKi}2X4Ng0S7eLW+?DjV=tAkM zw>MJphoyzRL0=&K{cJ5%9uum}4>|7`N0ZCxdr0K_jXEUTw>OJ3)yD~yo+2Tang7N> z*oVnLm}++tHjPI|ekcNe4i~GbsVSLSL`m3>`}lEArdgHUYutBDrG3}p4RiX55OO~J zgj@YwpO12V{xzv%dATczz4atDW+}aFX339x<>Km73&cue6iM39ki?L=lT^Jt?R)YO z3xKL}pGSJg>+pDL#4qY?P0GnOYWKd3mkR#L%N@hI-e~8Z`Pc$$xn`tNVE}egxi$3w zV%Wplgnx2aTytUp+yC)&gbgstSW@!D-{{FvY6$=;{SZHASd|~=HbZ z_n#W_qo9Qx8BP=psuz~OocM;%lx|G0VUarE)Q{KD+^_6c1cjjhn0 zj$%&E>XM#5I!}<%YhHK0fqZB+P;5XgEn~ zGEw=_-R`cgB*_yK)xkZ&nQ{aD{&GtSG`=PjJkA;k!K(m;&ulrIadg0TH04}yeBM@> zM_l{z5jM;FzhWb-+Y3fM)zmwF(?Jj-}eU$T6q>Lp& z$;rIgJ8~IIQN1B|)e8`BPX%*cUsV)X?wf}v5vn7OQr!2k83tlau|o;Z&aA%gi!;4E z#9B%6aXG|RSDPcqb*|J>QKm_zESy}n1*K%pWo`Ws7GhF)cMaZn>@~co%t#3V57R{J z1`XW(N>-tg%%BI)$7(|WhPOAO;9JSK)H)!;PD;0e;9zXU=XH)$|Ymg5lmIBS}} z>^z?&b=dXH{JlumUgSxJ8P?j~NNMI9@Oa&*zbs&0^~T@4+22C?`-ryuZ0b`GJErQt zBffCs;m6eFE3xu&1Ou-vbWtwNP=9(K8!a`rzH#yDT3 z!ijM7ywC`|8xE5kh(+L--Lm*w-Hy$|afU<7L)S$~-p)dCsnTZx^2IYgY&I=ip~ahc zu63rdk)67Iz8QJ@vd>3f1Byhl`WhY0`Uh`rHuU95PYH+^@C*?@n{GiL=3`xc+zH2sl zkW4t1N@D&6LRRPX-5#&|y^HoF`vewlO33qM3WFf2mo4+qQoHU2z2>=BXSr(QI;~xs zj}oNG318F?@3J96OsX;8?%3UYnb7G+(kO27$WBTXipRG*q^Z9nq^yi&#H_4%FA+|i ziQhHd&O_{9?i_%g(2O31i|^TC?avaiTX);%yHnsX>$k>0X2B}Kq5f!IAwAxQ%Z_+| z-{No2oD87`JFQz;ZKT`2fq%;j_kv3V?x28cM@u*R5Hr8Uiy7ocYV90jcU9)(oJCrD zJYc5ZIR&D*RiROBds6^iJ8L3*{0=BBXi1G5dXqU=_azQucZU2Sx9tdOcnLl{!)6vW zJO|-d!TWrW1FmM5J`}u~!QR-^qo|KfiHnQ#OyQ>n$ABE!c-Z0^-lg>W|B5wWGnj8E zz&+L1AIu%0kzu#n3|u4KLhZjS(*D?upE+fq_+3lD*egmSazLrf+mu2cu z>q-Or-7;+y3~_H_V+`Abc^;E>#&5l&qXD1B`0a<5X9+RuRMhN=-fjuo01guB>IBr{ zlJf0bAG&^KVKNFP#y_pe7JZxH_^?3d@ER|>B5>=xw2nbiR*Xr1hd#Mv1GA+{ZziKi zV&>4;YItZUd3yAfGB(c_IM}eI2fowcst#PDeP7G($))J5;b$*^}Bjc&kz)B}Mosqe(Of}~y>5SEg>82;4Y)s=Bq$Gx~ zAO36Zyt;r@F-(g+5RWNMm}ig@-6A|BWg9MeQ8Uq?#INDAvt9?frS>iLAN7Zq39n*0wzg&?=Fsi8rhtkBRxY!^Vx7u(6{-9E{_na< zTztB)L$h4)h*UnlxwS~xv}BRyZp))x0cUKcTu)E7EusfW12aB7gOTf4MVxK_7-b9_ z-E~1!6y-xbUw%^0yH|gP;DQ*wtAK0IO1J0`HNT}Q#1jN<_UKn|Oq6%9b9XSC_N_#% z#WHO#>6f+RD(rVurv_8zPa4h-&6h3q1~@_G_RrDJs!@cPYgC&K;#|=O{Ckh&XvEHd z?MdD$t44gMUpclxpkNTLIpsEeio|Sj^1e^$X2q}d+MX)~elMo!Y%h3@&D zirvvhnqrI3eU7*k8`&jOiS4ACrK8aFYPh)4p{@8)aPA#>tJivhM7;FTmaXrn{;H-1 z53#bw=IUm#v5az>;z{znl2I2qO};FOdM&v}kBtt7#;^q2${hja%XJ5R{Hvi!Pqo=G zQ{AoTg9IAmL$&5R3p>GI3z3OHX{nGk#1|+&aIf4#;ZpCf6V?5FYvj{eDS@z0E-&Zh0m3Y``Mx>W` zC4kGF)mb`WYE`jrdfmypc#N|+dTU6R& zB(uY7G0TqG{vN(T37>4eW&$YFsT3GsFqM{jC0!MeT>Ta3XZTe2GN_^wJ8mWFvb;GOKkwr?ek|l?l;v8LsXer(v}>=i}UWS1-NY3J1rR z`yac3+9chhkvGS#mgStNU;pz6-6O#sq5Bo0&@zEnFhV9gE3dz_Wp^^04ey#Hd?)}9 z&ns%E%0BBi)7=yXsjkJNJFMAN@+9pFsveq47oDTF6& zvhE~3G6DMtbugM`U?M{WoEa|y7<=IVTJ4qKY|SE?9kFi&-o5 zfoU4`?1jX)ZbEhH@`^R4EibLsa|@MAq{Bn{^mdF737V+sE#5+!Kw(XRCKkzC0s3NS zwXWQZMy|IVaf~zHYXA-Y83&oUY_@qfe~-5u@0XZl% zRua71s-4v&x^igbWz)Xd)l4BMQRNI7iq|_etyO0SZZ8X?yT~2C^w-~^UE>+Ol2Sa! z)o=FFS(7LP64L7@W4D-{m*63cZH8Kh%v-acl4{xzjZ%zef4cMst0lSbP}s$(waL{6 zqy35UD7%0cDl&%vXT%NYH~0zW*FV@1CioyHkE2e~hi?_*#(LV#!UHTr&CVl^>&cFb znMRD{v?hMb_YSF>7K+ikXJp|hI>ne-7Iu87H!QAU_Obi3mL2nF*H4=~`N9WIol%nRWJPx(#piFgoPc$MSbwfurVl?1U+cEJzsVB}vsebEM z59t=pJt{$i+hEwYYW-KR-cXL*uT?MpJ}z&<+p2?W*|8T>$UF~`lNYQmCps`7I^n(6 zR1ohM@@5B8A|k^n795A+JPL`kVT0^=fMNoq7j~>f9-arVpIP4sR8k5;nZ>XLK{LO~ z>Bra9EIziDk{YCzXD+?*iEa8-yF()#RVjtJFZ&2jMTGR9f%r4FoK`RHO7rAsuNJIZ zVZb*enXR%#t2$ULs5czH(PpiqOt*6~D8*7d1(aA;m>PUhx(GbZK%BLm^GgX^jgh5%QPs`)C{yk#Xv=js<4B=% zW!9~a@rYH;4NB&9zhIN#&uR|$BBI{s$<|CrsC%kV+0)Z=4{vO03|q+L=;#QBh*wRT z8H+@WH9~)kmNwuRc@r64PTQ_fS5N#-GJSQH8Cq;!V)7Ozh1#+J#znTy(b}x8HqcMzKn&avBLR$dy=!Jr4y-? z8pP9{+mdQ&e?AQTwx3XLkA$dxw|+Yna=krfc!u|^y>@1;#r1e9-qIi$T{6|kMkJ%& zx}Us+Eh{X}z5rfY;kh;F_+sz-uwMd6ny3qha{laCPSl&&&wUN{fBD~mA9&%$eVykL zi}^>S6z~yWZQ&vvQc%_B_VnONG2w4#Ck(A5_xRMQq0vk!Q)%vdvABLxJU3K#O{CQH zT%qhVklWp8pNh-IV8H1=*5NaQ*$@n*%nK2H|jA>Rk0j45MMGpW>vE_Ve%j>Q5OH!4(_ctl9_oXUi`0aDdNrEDoUJ z3PHu@oMrb*R0T{d!@OM4p1_jd!6%O7^Ud4OidSGs)oO}jldeEnbJKJooKuMnYE$WK zB)Tz-e{LxXZ4>OC?r#ky;D7#{Ew}f0e?4`cE;Q|aee?mFHa$I^x4@$glCm#+!5Q^D zx6s33R+Dw%GCB6m?Nw=TG}2Q_x{ijjmD`|x;(4XFW|dt{);CM*jIe`jIKp}C)yIUL zlvI?rLvvIwa%ET_4Igy4$HoHOJ%g{{HKaHov|nWj!w9!`Iqk*=e%C*3q|xg_x2aW7 zF1=0|q-!3bDS#RXq(Sy{@#x&sofvj zJr)=#n)iHqdWsG{`)*g?wA4!cxaL!Mu>U#FbJu+}rCHWJO?5n>c!*k5PLwrt`7X~; zyTR`B8pPunZA)RYZ`WALRkOL?%%18{xOmlz1DS;WgY~U_NQcu;=r2YN3LUOV@1q|z zsX-3|XRjCL@}3rTMUpfDio%xDGm|rT_ISvz-anS+EY}Nn>(Q+kg@L_gR|hZ*wXL3w z6mM82<40|m0|_r`x7B))|Fh8lS(Z<3-tFS#nemS`?7+h1(@~@%;L>mHdWzPTV7MKv}sW zs>tcs1Jkjiw*V~t+K;DXM$*IkP~(&R^YU>ZvtW;~72(<8__O(}`N9t*Z~nhl_b+h1 zz5Ki*J5OrN7rW0eg$@Y`iQ1l~dx6e|g4$&j&b4WJR;F%&ecAE*`Kr6q`OPE}66KL@ znvmwc(8NQEOt^S)(bCOjodiX7o*@L+v59LcO1-n-t!{suB<3890sn7aB0qUmRh8__ z7S7W0NnA;)+nEdMqC7WJ8=Cp3F1bV9@^JV0!Dw@*`T5ApxBJ)b*HV(HyMtCQP$rZS zOcFYn{(U-JIA2|8%P=u96_=D)Nd+lUE3Ra$s0DqLW-+$tnj|I!e{{Qj6ayYV5`P-4 zK7E#2ywN>9qq*`%tw}@tt!Z5PV8Utn0)@?`4l&|L8_$+zU4q(50l6<((;~+btij)G zGukVQlt2@riZ6VxfRiD>Yp{EciAfC~-iz$na)ClJ7iNPYVJG7m$3ix}%*E?s08^VO z3kwFyIjWIk%-`0Gx_kO3_6$CU!?>4y}$M&&EbAgdgwg8$LkrOlnnMQyFnl|G#vZWX5>gue22m3E4iEm*uS&p@v zu$WHv2KE=BwWzk z#X;<#5%hXjqwsxN;Z!(#xvSebx})xs;A4z9^RZ@%1Q|%mG}S!5o$bF8 z>chGJzY!5-*8)}}r%;7n{e7fA1AOs`HyIp(yZ_Gx!h)wm4cz+VFsAVRpY4A~)4R7{ zq^CqaIR5?bpDpa_u+-fcDa-TU#~cpc6PAAMX9ckT&o5J`VEIv{{}}f_yF&5t;ePR3 z{!&&Tg@D{lG_dnxvPfP zc)NPZR~fpY6z!NZL&@i$%Ej;V66p%`Jw2fXz)$j*qtCoR+$8$yP$edPeWHMj_W`mL zaXphxBRoU1d*tSG1-o1vwaOhDL3e9(EMd-nvK=td4vF{CEfHs z^WbN34>N2-uxDrK)ypzh1vTV^0W*;W80zWTeBzaBx5+D&R9PKskXobP_0uw4!rCae zExp&>xjzIF&^A8q6yol)*eab=$^as)mgG(hR@E71;bU|i4z5(D6XAY) zG-Vk^NR|2`afz~OgUl9NP&CfYLB9g_2K_vXSmYR2*4CnD2SU=lrW;7DhctK*n@C<> zKSvHK%uS8)de1h9tbSj3n47`KuF#pa(OfX}h@%4o&KKIJj-M#4Q)aK0UfX&{ZIa%z(d{#Qp(XCiIi+D6xVYIpH+ov^%IUp2 z9Bk@eRueWjW}$Ssi0Of_pA9Z&xL)swq2Yne^T(Ioy-%eZ^{Y>=*eDZ(>PS)^e*e)a z!k?y?EXSNK2>t|sxTJwnY<_pT+5&|XhtHHw!bVMk@ZE9u}%N(qW>k( z96kPoGOf5;NnJwyr9o=U%SX;T<(1}0yO!xr=S;3fGc%^eiB53;3eFzCll=UMwOhJ~ z_a}8FaXM{1e&Lpa%AE_p1q^#Q~3}Fc-S57MM= z&ef*X*+gNx(EcDNFJneNS}Ak6v{8UXu1u;wVB!zts53f_4GC}$$K`$J`R4t#O>TOv z{~Vq3c>qc~+5J@EVU&6)==u5!o3H6yzwR8KlYmgdIA#qCZq zc~?h6YJ(Xw#KhG@y`x`_PKshw-$(VS|5w){V(@oo*+>f9RTj^N5nj?~P^k9pW^d1v zMUbCdj=|Tc-vKhoOrDv|wyN9h_!qAE6jX6^Q_)G|YiKX??!)M*8=Y(hTR6fj6~(NS z&e8Ia;a(TK?7Ah8it}6uyI<_OLa}tbX27@`ymE6CzmjmiG+jNGhkn3 zd)1RvojdI1)roHggpbK_1~fqGJ6%qZdZDq%~mYnnY_DGAdj zU3~iYIa-6#BUjGYnu$@WgBLg)YDZ}wb+bHi>1lw z?kw*^f25hBB@dCt#I5ZrT8_#GhhY7e0s^x_hAhgqdJb|=BXbywT(r0+`{Q5sSy|}( zTffTGyOsynN+(B+g(ZDnzf`c&`ON2-%eq1Ma;pSrl(L-(<-v;}FuoA2LXaK4W029UOlH z2X6C*3y?uRbJQ(F!0UbXn5oJMPrVp#y2nref|WOoM(>*JSCiyff5Wc}y1h8Dr{=5j z=~=2$Q!SXB)K@rJ^qMiqmEsYamodbop07%! z=peQQJi1$SjH<1&-IFGsbL;46yxdSdBwQ zHi;Qxj#?sq!t6-P*I`^&81*`v|ReBKsG zrHN4w{X&H$U7gO3bNMP7*gLb1Y7CYKmW=PNmHAXyky&z(v!YWkKNZ+)ce=o*SO3|(b#DzFQI5`jP!;J~JD8PnyuH#zs6#BT%JZbgk zbxb1jA#Tu}jtuC8)0AvfQY^?m#;NuV_kqrkLYH@ozjxV6}A=h;d-w`!zhPl&&k63oDucl7+6N>znaOYjhjsvSbY;=o?1RasF z`sHH3XFf(pr!Rr}kz3~E9KWSy+IZQ!@7F=0jCG~qs?5(57MA20YWk&0dow(C z?TU$^c03F1tXGEC)5oN)&o)n{^-SG8)@isi>+SC(HVpXf>t z*yvc(FDZF)P`3S(6T2w90zFDx$pW#r$CzHAgDC2L@+-2>%mLyuqCMhjVrS;kmtWV} z_!U~NaW){!gK!cOQ{4+`S!_jKbf;!DYfu&KrX=lO=|0OkT-hDa@fsA?@PS8ZA?tg&Dv1WlFL?9nLn%CpOct$7$;7 z>(g%ckEJSwLivX^qZqJ&Ahw7Ky`xk~R*>eGX8B0eghLoFlJvwVw{5-h)NB`myK{^se8p-R*G14M0a=J=yYhbhz`9^~I0CI^u`q4RF4rZEC z0sZ)a3#t6RqqAO`kTc#9t1>?@ROgl-uWbLZCl_m!Z2cjXbzVV-X+Slbj`nC$&!_Nr zeNvPSW9<(&N|vWpG1cmEg-aT>!*I}wC(_js9niLXF98XOChu4@UF*)Zp81JMpt7;! zqBC%#W-P3Pi2=jb8v(^!>PIEx@SiH^g4Z|qd2P=Ztu68cC2xd1;Am3+y+X)7qCY>^ zeobX?0id~2!F>8=j^#Xs@cYuIH1Ft|m!rCZ=3y<+%-95(XCyLvIp?h(xc)@+#k^DP zEM0j9JN*wEjk9JJ@2H`s_0`}(1>t7)L8nf_$K*YXqK6oS4apT%_J*}BTOv2slJc{@ zh)G8%5?N^qXKGmp1?Xz8Gd6CC^R{x5Qq%&vPS+NjYT}+h%@L;k9_Z+7+~MD85h`FP z@_Ja0#f14YW{K8IX{|w?)VA>XNpOU$BXDz*BQY%#vzX35zoUU4!o5!wSsfn1Zu;S2yW@o^&otZ0b+`_lFWUYm$QhC+=MwJYB zyM&ywnBJVvI-m3Adf9$!QW~~ePgUtU#((%ypa*MQm@)F&=R5L}je@uKLPv+nqdK4Q zcThWxUpOMR%bUb>wCNB6JWu&vI0w$QGg=I#(>qj&Mo}dVEsI2vKi{-_Sj7l=kEm9O zszwbeeYz~*29|{^?0-2+#*p;1>9bJk)TP^++RNcU))LhtQU$Nkc}_?A=0G5olub~) ze$Pt*KhLYKl~}O-F2M5ifC+V(jZ2~c@nd_H}=CM5cbi=@l3>>Hv~vq-uDLlhZ>oea#*ac0Q-3{ z#R6Ynw^e7T8VU(v=v(M!;Ab;!%FinBN&Hf)Ca>+D#x>t_?LqDx^2@Zis&cIjJLGnO zTg<<8l@%C3kSsfy4X=~jDk`f5SxGB8X3t6ZS9M4Z9RMh^6??upB_g|;NS=H(x9e61 z4}Ta-WH2umvqao@a7_A$oZR9P5JLBZ*ZJw&ZhcLHV(RgQ z0Jsw(BUyIClzZ~AE`mpLhz)4H-SxpKWv91}m3re0_ox*)>#fb7vQ>*Da%T_OGq?(h z!^D2L-p^FFK4zeBFRd6(GCYQ<&!O^CRdGpM7MF&L=l#ys<*O_gL)-$9F&j;&N>r2A zcTa;9CU^MtS#k5IYA#mcO+rDqW?L&S2mCxaqOIZ;lh_ezu(QpiCishT>8Dw(Z5@h9 z_Cbo~mkN7Sir%z>F?fBl3T4(*ii(w`9!&MOP=PzMtAti&F-u2Y1=Rx@7E5|-6PYX< z0Xa%<+$3PZk~+Z8;6DkEV!GzNJgki@0rpO%iO!DJ$3yFvZ{DX5!n~4yipD-PIqrd$ zb~dlzXhcmqFVg184S}Y0~rURnUU?0C{sPD9TL? zMn6VSkPuZ%0)EKw6(;h2dA98{cr$(P!<3+uK_h8^ajBlj?2-)27RCU7}MJEjPJNba&@uy_xB8 zBKMFC8PWMH;8c`KTvUoBnF__nx|+*qetj17(cg6MJsN7Yess(`f5DjNb$sUM%I1RC zXxjK@-x!U5@dpduYVCG){n9j6%sbiH*R!BGz&wWNd#tRmjx24%O9WYdz9RZj)J+~U zEy94@LxB@$xbQ6yG=oJDcIR?@t?I1p(O%>Kqq-ZD03Ik}fY|d9R@1u+Zl9q{l({$! zgl>0-rQvdA`EPE&j{1w@!Y55PP8M(f++6^3!%ku}jn2t2R8_@!UBF0QUbl5E$6?V# z#U%Jsm*|UqZf?tReo1&qz$3}*fpAN)f4VXaHM1P~{{C*iy(f+R%pAPdt$^hmu0=TS z<7gVSP*BT8bn&_shXkygR`a;%gOT_w(R_dLSDqLho zpAWUrwV>A#-jX=tfU4L={V^WMipn+1ITT{ej4fug*nD1B7! zcWIX7qu^r;Px`uy=UCaKG#c@QI#!pl{wawGX1o3uoW>i7v`d%=vvZjbGcz<4Y8Qc( zP|X|sx|GG>vz48twU?ecKQlkUe+;}jR;4BDH_v=dr2F{>nc#64A#1K}vb{5kt-<*A zff#}2IY|Fa<3|FR+L8`jGlbI}$Dpd(Y;H#0-qp2fMlF>5kgEh)CeN{XzC!+JNC|zx z?G>gjmUANUg?zc0^?{Y)8>3!8-Hn66P_8#({Kz?~2ub#0Dl_zXe}B`pz&QK=wRh#= zRDEARB0@>#WUjb`%<~W-^K?mDJo(W}^BJ+67Lgo-chRpLd3z=u`#l4369^Vqr z@BiQPyzldV{pXx>_ul91wf9=f|LGBV=3|&({bG9&zZ;r3X*tNvewn%b3$w@tC6GP)X3$* z+~gr`19TZxy>J z9$RNV_uqVh5^oxusJG)ZL&ms6>zpP_L%mE17zrkd-75qu+hijSi#+P#DROILmIHq2 z+S{vEd`HdO!`Th!i5VLrqxyXh5u{_9K=>$i$+Fg(}@vx!j>35_4UbQiGMn?u-!*57A)gXjp z#}UN^oxh0W3Q=<-=|hL>_r8`pCi6G+37d=TFmj11o<(VW*@=30-E&6{!b7%}60krw zGbQ}5qfQ2af1*e zVt%DgLUY9!mc%@Ifo4MwPl|6E)Nc*sEro=-e3feA5Y9LVq7^yLaE9v8%166oEdeFmg}&Z?E(Igy zuX{p;?AAs{PMDvDo19p)lH!#hLzY#r#Ni=JvNx|se z;8UZCGwk1?+9!E6mxrBC)%uo4?_IPgx-3sVB$vB-LqYEmh8l#W(qsF0DlB_{$E4Ax z*O8;9pH&ruN*wHQ(tP5WlB{JafRd5!E%nlo;)S_c$eT#z7w(tcYbJ+2@{;a#bo#y) zf?qeiy*+AJylLx!4k4@y^@#9H?HLIRc|!C|ar!dd=c~AOqUEw&_Fs)XMURDU!P=aU z7%RSey`$+ME2X6+n%#cBsj{x=&a}v<#4Bw16P&f zN7m-9bT2Je0mrL=lW@#n#P&9&;472T&no&AP0G(*-=i{9FawV2^d8m+fA9**7b^Kx zYEp8D*Um{Eq(~7g0E&SOg30Ho(l~Q9fN&E-xeN{@)T`e$Off69_R7Lq47*xK)caz- zJ36Q_=SX6Uu#X&2mU|?2nIlHv*b+CCnuZhvJ4=)Zb*Z-{9uKT1mSI4;N?pc)O4Qa2pXnC{UZZU2_-q`rKIIszM#P%EgxUQICkOK*J!D^{J zgd5iH1hFswbk9y9;YMssX7k5r=qg-Yd)Um|DggpZa|d)MFy#S3D~@N133gR9AZe$$ zgLuRtUS?+*seywWPV`K|eDJoPdZra(h?wKYyAKoHk`_Fw9#rfT$!@%tUKbv2Fz0#s z@|A>q;Y_X-`vOilTtP?3nr1>ne)s#ZnLJzB#{h@lsuGA2+WTJj+Caxz^*6Fn`){ch z>qN*vId*N`!FjwICFx4Hbb<)Ke78sA{G|KCRoPm)x`eDlLvi}(xo2aP%ah%lA9qYv z5P7lY(KJEnqE}Ybh&0c(Di=kp8_W*B!iLAL^hPQSRceFR8T z&i}jQyTJ?u;Do10L$97Ue#wqS?DE-APs2iL0MO_Bm6d|{On!iyvtSS45c1!qs-Zv( zZNmk~&UW_Mft%lR4}b$Je;am?1+GkP7d}(G(0HK6HsyIF@y1d(W{VqP9>6^N^5vjm z2piKkEKI4$An*Dg>PuISk5fUR3uI z(Y{ZjJ_k7KOFtKouNPH!->%9h7jyW=Z3SmjkK>)M;Y%1zcz}MLs`o}0R8GC`nD;(G zX4lqwh76=KJFN~Ez)S1u>Y6dB-#=cDF%Ys}P>l4;&kr;-*)K{I{7_+=-<0l{5?X9w z)eCw@Zlk2+-XMx=XZd!5gy&qo$3UsxiSpDMaO9-(^beDgtHk$0ZwtOBlv!qCgWjT~ zRKxHpFUOw+6B7$EChjdWHAu44eVi89+bi+5Hb8F{!4x@dbp!8zrr2ArobHcB^8R!x zNf$bw4+&vxz(ztEAm2rG1I2{`oIMgzo8IV}l9E^LQ6Q4MytzTA@RG10tCiKTFG*Jx z!s}SgX@LkuU&2nVlpBmZN#RMUptO8J;3S!6Ng&x%?4A4?K3jmyIPjZO)ZYW2DvS^- zf4YT?@~x#Djn=ms&LCyUc^wm@uk~?@HerfoqWX-Pq`kbE;=yIuE46X|`5ccb!CwiG z@G%@iydjoOFZ#NJXDv=G>c$fx_t4V7U@DA?AE?f>B%RMrmh~h~Xr8c!$bf*ct4`zT z$5LSr`{22bG*&GS3cBv8uMR_*?d?&T`TfB%9u(zH&4(Q1rr$ZjYVN#?F(H-9#M8OV zK84)ND{E{>BT^$uqgh^d#gn$PE;5L2mLAOoz28n_O=s|+4t6R+dhg(Dbgj=;L52T{ z)>h!vGFIhGY%q|^$_-kdn(Cu>vYUcdeb;_@J1sBm^Ydp2#9B8vGo8y(_LedKI-)+* zV+FJr7ea;?*T{`Mzt#cy57v(F)qTlWiPSIgPVt5Y$g)=RK$64-1aOho1F zM8EiIx!C)5(zGMFD%>PC<=`5DQE}|_lYPQHzmwqps><$P)yJ8vwlkeQ zv|0>~J>2&aFQez;dv*AE#3GNAnF zY3LH}UwLuB@pTfd%G%F7perwrb1=MP-py=dvN*5bE{L8^AuRF|T?>rbK7Lu@sBc^J zji__<+W5(C4Vb-4^ycx?&Uzc>U#$#`;x3E%)0>n0oUZ8{H9jm_tzQ=WTEm{jju1la zZDM|9ZtB?OyfaihxZ3~0`}T#MNuRN|5CL|(egg0nEB98jo-eC0lQ?PS$lC!<2~)zucGgTo0>=O06lc z)?4a8Z1?*<1}>RKT8XFYZ3hy~hLCr4g{?L(07tAsunyRtM@H*wH=mPS=z0Y)F;ROO zqB>b4aQN~7kO=tDZ&m%B{B-`x^0M6ate-*!Q;b{Mc5m7!E_UP~h}wg!miF!kkUvAD zUDM;7kCOD+5QDon<5Y`Vs(Ii4(r-;Nz@vExf!w|EYvXD4ia4W@(c;c@6Huho)bc~g z0sAf1*-sy^mr56 zp8Qx;Cu@$M*czqvNHPN%1PvG}XmRfU41?%T2ldL6U$|B{cc#>6fw`8@b{r#u8)*gee^rk2`obE({ z!T8r;G39j|sOP5^KLJE>^1rTcG(1Qes_dK~05}}QiJ2~UTsJwpN8N>KY z#l}h0OhH#l)SOIZNn-nL%VxDhav@%FUs!Q`>MrQC$AH@FpuOy$%~nH4dM=aE5+9s@ z)#Pcw&%E(}bS^c(T5-HYPxbdXiEnhkrE87h$`=SV4yQ~R4F4Br-xTQ054gmOD=c(@ ziqlK)BcO?MqvXO52^f3?hUnIoNY2}rcnc_DYKgW}`p6$e{2&mxaiRVH`oMap z1T@oB%LF!1DAaI?&i#l-7kbBijz?i-AhL!Gz$foc7PYdlproJ}$yT9tL;#hLqN1Ym z^78EFTCP#?DJF&gCV&5#r82cteY+KJ^dTfu9mpr`4HOu2b90-jagK0XhZRATm6ZWh zCkaTpUDPA8OHfcyVaK!1n$;$}I~M^mFC^pU15%elV!1kcy1sg{rStv$Mm|1iSnvo9 zcf^V`{W7qRS}YkA3y6uG013hzPT&J7K#q*ql%5YNVxSwi)pW|FxW97qr>7EH17#1o zx5`0vE-NE-2n*0j0$)ADMmqDTs`HHtTeYmlDTN-M@YK~+P;@kVWN>T@wKLyA&S3zq z+?}xR866+jz-TY|{P{-Eqm@s}LLlLK`@SshLLkXc+%H8#PVClwFQla%e3bm7jhC^@ z+#7%873wahuuGm=KyA93EDrdYP2tmk4cAl2l-O#EWCUuhWkrLjs1g7qvMa9l1RV58 zGU8BZYw~pmCq(B)m+(M_!@aVEa^@Go3D=TlFWPt#7^2hr*#d}@ z<3pb7xnQ^TG2UP;-c}PEo0C>rZ$QFsT^kjc~(VQbnqXh00 zWE8cV;mluUP~_4t`EAg#tHx-p?d4yS+qdiJ5ZMV zNLw{JD(YyfiLi{xab+;K?6dr)j$<{nZ6evQys-|OKQvGkk+OwEyX z^PwYe^{q`Su~dVhP&<8npsG%hL9MLIxTm*-T%^SZ+bcJC^wgTSH)@9hJab+W%?UWq zOU}QEwf%Suzs9@pz-FqS{@8t&dWPwIF-qV7uGT~frkJs@v0HhHK}tHnOMe#^9W9N) zN?m`vM>Ven1_LEC`^Ld#EOIf_JV3!(JAy4ElGeSgo@u2=@RBg=`nq7MGT$hD>iLhd zR(Vu!?a(wyySi9A-cZjxNtuS;Te+&tzl7gSb7(aeEQG>mN%MY?*F6mAYQ}U`3kyTT z0EYNvovHM5iJ9e*A{FvVKCTR@bFXEI>C|#hqdIN@jlCVyX$=Sn@DLcGpsUa-^IRUR zYqcVBQZyV)ATr;WB^Z0*|a|UXG^lw}V1G z(D~>iuM{F3xT)|Gt7YJuaekt~3md;G{^?gNQXxDB!8Ix~9o6;q^#PuliAhHE)JzP| zo9Zbkm~~JfaxH{9Uwmeq+`Y$ZVDE)qQ;f}M;Hb}g`7vbOzS?$6&%Q0ecn{fa&UGkZ zYhTMSYBa5Gxo?_H4jo=mGKNn%wv{L3AHD;nBEMUz9bT8V8CJTiFTP6c{o~_E8~h1h zU$?MH;afHh-427F7Z*Go#&NxPH0?KFk1el@k{5k|y6NM(yU<52ovR_V=|9YE;fF!Z zOCk&#jExm(@HS^*6d-}^YU-m&Qn-@Tvvg5R@cKAyDq^W5xH+kuy21I6O}{ws zMRG`JE|FV+GD5*wsk>8oe9KXyIbY52J>(C~eaX(WFwp7XX@8nUMmzW)S7es`CHe6V zmX@kGZ%fbI9kn2jBO;#oWWf+$+En!r>vOW@4JQY@-<~v3bgX6;e2Ygq=O~RA15X7h z#afG_pSL(Pz|`;8Nh<>Wo=dp*kp1`i`AJ0l9A@ub;^J>C5P!?NbciWpq_)-J?=U2s z$)4LLjwLM)pA^$eTG!L-oX-ggSa!#`D91NC7cAZz&riL0KFKtS3kx*n6lqYmark`z z`=6(KWdKLs+Fz3MT+#colLBBv=ETwkXD>AjFo4E!1B@Fq53})c%-7 zOX|RQ_1nY#!pp#S7&`?%!c>_rzE&nM-kKnm5yDa?xVvp;`#jHatgRmt-7 z7EVrkfYLm50dy;Ef|_R^`dtBHcauQv%AXB>^(QDR?e4%U8g3w7M#TG)7)znNsL(;K zObH;!swjh(R3>o8)u8bRIipR=wpj55JLtk^)2B;abhG4OXSmP7kxj20`@j$g1Rp)Y z$H&)DSMMJfu#g+-?k>c?C!wzj{vFyAnsGPLQ0&xv8m>`)?8K4;8`_Rj^3u_XeGrVtx1W>3|tD?3g`IFrZ-lA8nN5HwH=HS;&R+3`MW)#aS{08X#E_s%h zVuqrSpF>-S#o%9HS+%HJb@%4gyA9>hM#r+du#7g%zRwKCtFv34uHY-Dq^du-)oC29 zDp>~tQQ2m;Ue6%b(ar42bx`hONfHng1nSsMRoQ1ZwW7XV>G~TP%ZUvN`Z1&jYWl2@ zC!YyUW6t3JYC~gC&Zs2D&tRFcHI+;XDTJ_~xL%pHt$VKvYTn)&YfLlhLnam33PHEx z550UC?eCyEx@Kk!A+|JnAhvder%A1$u?IUQm4{Y*caJJv#zKY>wJi91rjKPkwnzdR z{kOgq(-WUt{y)>O0Sor+b!vGcmVoCZX{Ys8UR6!BwFR<+z?lNk6+h6kDbs{%~Dk9#*8>s>)Q*El$%@#UPKu+;zaamZ3u|md-_^$hkF^pf>6Z2frxi%kB-D0XdWJ}8|Qq8whO9;Ro{&o1@ z(u)E=f)D%6Fr2)7;PM;Ss+xa}7Irqr63+JMvw=V(w1{o#H*wSt6ek5~v0w>=o?Qwq zmObR6yOtMg`?r5>LLTHH-GzB{pGTJr7l0Y3JVc7xHs(noiqwxdtIg&FHvi+O&7^#)e$O$e z0{TRWy8=ogRPFVqOV~PD5^9NM@V^%G_;+Au z+UWm0eD&{C{yUZbZ?W5dh5ujS|KB0}-_V4WO2-rkli8b>fIm5Dffl^ diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md index f0c2a45b6a..5f8bb57365 100644 --- a/doc/integration/oauth_provider.md +++ b/doc/integration/oauth_provider.md @@ -1,35 +1,80 @@ -## GitLab as OAuth2 authentication service provider +# GitLab as OAuth2 authentication service provider -This document is about using GitLab as an OAuth authentication service provider to sign into other services. -If you want to use other OAuth authentication service providers to sign into GitLab please see the [OAuth2 client documentation](../api/oauth2.md) +This document is about using GitLab as an OAuth authentication service provider +to sign in to other services. -OAuth2 provides client applications a 'secure delegated access' to server resources on behalf of a resource owner. Or you can allow users to sign in to your application with their GitLab.com account. -In fact OAuth allows to issue access token to third-party clients by an authorization server, -with the approval of the resource owner, or end-user. -Mostly, OAuth2 is using for SSO (Single sign-on). But you can find a lot of different usages for this functionality. -For example, our feature 'GitLab Importer' is using OAuth protocol to give an access to repositories without sharing user credentials to GitLab.com account. -Also GitLab.com application can be used for authentication to your GitLab instance if needed [GitLab OmniAuth](gitlab.md). +If you want to use other OAuth authentication service providers to sign in to +GitLab, please see the [OAuth2 client documentation](../api/oauth2.md). -GitLab has two ways to add new OAuth2 application to an instance, you can add application as regular user and through admin area. So GitLab actually can have an instance-wide and a user-wide applications. There is no defferences between them except the different permission levels. +## Introduction to OAuth -### Adding application through profile -Go to your profile section 'Application' and press button 'New Application' +[OAuth] provides to client applications a 'secure delegated access' to server +resources on behalf of a resource owner. In fact, OAuth allows an authorization +server to issue access tokens to third-party clients with the approval of the +resource owner, or the end-user. -![applications](img/oauth_provider_user_wide_applications.png) +OAuth is mostly used as a Single Sign-On service (SSO), but you can find a +lot of different uses for this functionality. For example, you can allow users +to sign in to your application with their GitLab.com account, or GitLab.com +can be used for authentication to your GitLab instance +(see [GitLab OmniAuth](gitlab.md)). -After this you will see application form, where "Name" is arbitrary name, "Redirect URI" is URL in your app where users will be sent after authorization on GitLab.com. +The 'GitLab Importer' feature is also using the OAuth protocol to give access +to repositories without sharing user credentials to your GitLab.com account. -![application_form](img/oauth_provider_application_form.png) +--- -### Authorized application -Every application you authorized will be shown in your "Authorized application" sections. +GitLab supports two ways of adding a new OAuth2 application to an instance. You +can either add an application as a regular user or add it in the admin area. +What this means is that GitLab can actually have instance-wide and a user-wide +applications. There is no difference between them except for the different +permission levels they are set (user/admin). -![authorized_application](img/oauth_provider_authorized_application.png) +## Adding an application through the profile -As you can see we use default scope "api" here which is only scope we have so far. At any time you can revoke access just clicking button "Revoke". +In order to add a new application via your profile, navigate to +**Profile Settings > Applications** and select **New Application**. -### OAuth applications in admin area +![New OAuth application](img/oauth_provider_user_wide_applications.png) -If you want to create application that does not belong to certain user you can create it from admin area +--- -![admin_application](img/oauth_provider_admin_application.png) +In the application form, enter a **Name** (arbitrary), and make sure to set up +correctly the **Redirect URI** which is the URL where users will be sent after +they authorize with GitLab. + +![New OAuth application form](img/oauth_provider_application_form.png) + +--- + +When you hit **Submit** you will be provided with the application ID and +the application secret which you can then use with your application that +connects to GitLab. + +![OAuth application ID and secret](img/oauth_provider_application_id_secret.png) + +--- + +## OAuth applications in the admin area + +To create an application that does not belong to a certain user, you can create +it from the admin area. + +![OAuth admin_applications](img/oauth_provider_admin_application.png) + +--- + +## Authorized applications + +Every application you authorized to use your GitLab credentials will be shown +in the **Authorized applications** section under **Profile Settings > Applications**. + +![Authorized_applications](img/oauth_provider_authorized_application.png) + +--- + +As you can see, the default scope `api` is used, which is the only scope that +GitLab supports so far. At any time you can revoke any access by just clicking +**Revoke**. + +[oauth]: http://oauth.net/2/ "OAuth website" From ea14429b7e1de6d0a61bbdb8e8a198a6b0c28b23 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 3 Feb 2016 13:56:23 +0200 Subject: [PATCH 67/89] Clean up environment variables doc [ci skip] --- doc/administration/environment_variables.md | 65 +++++++++++---------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md index b0aa420e05..e49b3dc139 100644 --- a/doc/administration/environment_variables.md +++ b/doc/administration/environment_variables.md @@ -1,56 +1,61 @@ # Environment Variables -## Introduction +GitLab exposes certain environment variables which can be used to override +their defaults values. -Commonly people configure GitLab via the `gitlab.rb` configuration file in the Omnibus package. +People usually configure GitLab via `/etc/gitlab/gitlab.rb` for Omnibus +installations, or `gitlab.yml` for installations from source. -But if you prefer to use environment variables we allow that too. +Below you will find the supported environment variables which you can use to +override certain values. ## Supported environment variables -Variable | Type | Explanation +Variable | Type | Description -------- | ---- | ----------- -`GITLAB_ROOT_PASSWORD` | string | Sets the password for the `root` user on installation -`GITLAB_HOST` | url | Hostname of the GitLab server includes http or https -`RAILS_ENV` | production / development / staging / test | Rails environment -`DATABASE_URL` | url | For example: postgresql://localhost/blog_development -`GITLAB_EMAIL_FROM` | email | Email address used in the "From" field in mails sent by GitLab -`GITLAB_EMAIL_DISPLAY_NAME` | string | Name used in the "From" field in mails sent by GitLab -`GITLAB_EMAIL_REPLY_TO` | email | Email address used in the "Reply-To" field in mails sent by GitLab -`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer -`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer +`GITLAB_ROOT_PASSWORD` | string | Sets the password for the `root` user on installation +`GITLAB_HOST` | string | The full URL of the GitLab server (including `http://` or `https://`) +`RAILS_ENV` | string | The Rails environment; can be one of `production`, `development`, `staging` or `test` +`DATABASE_URL` | string | The database URL; is of the form: `postgresql://localhost/blog_development` +`GITLAB_EMAIL_FROM` | string | The e-mail address used in the "From" field in e-mails sent by GitLab +`GITLAB_EMAIL_DISPLAY_NAME` | string | The name used in the "From" field in e-mails sent by GitLab +`GITLAB_EMAIL_REPLY_TO` | string | The e-mail address used in the "Reply-To" field in e-mails sent by GitLab +`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer (supported only in Omnibus) +`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer (supported only in Omnibus) ## Complete database variables The recommended way of specifying your database connection information is to set the `DATABASE_URL` environment variable. This variable only holds connection -information (adapter, database, username, password, host and port), but not -behavior information (encoding, pool). If you don't want to use `DATABASE_URL` -and/or want to set database behavior information, you will have to: +information (`adapter`, `database`, `username`, `password`, `host` and `port`), +but not behavior information (`encoding`, `pool`). If you don't want to use +`DATABASE_URL` and/or want to set database behavior information, you will have +to either: -- copy our template `config/database.yml` file: `cp config/database.yml.env config/database.yml` +- copy our template file: `cp config/database.yml.env config/database.yml`, or - set a value for some `GITLAB_DATABASE_XXX` variables -The list of `GITLAB_DATABASE_XXX` variables that you can set is as follow: +The list of `GITLAB_DATABASE_XXX` variables that you can set is: Variable | Default value | Overridden by `DATABASE_URL`? ---- | --- | --- -`GITLAB_DATABASE_ADAPTER` | `postgresql` | Yes -`GITLAB_DATABASE_DATABASE` | `gitlab_#{ENV['RAILS_ENV']` | Yes -`GITLAB_DATABASE_USERNAME` | `root` | Yes -`GITLAB_DATABASE_PASSWORD` | None | Yes -`GITLAB_DATABASE_HOST` | `localhost` | Yes -`GITLAB_DATABASE_PORT` | `5432` | Yes -`GITLAB_DATABASE_ENCODING` | `unicode` | No -`GITLAB_DATABASE_POOL` | `10` | No +-------- | ------------- | ----------------------------- +`GITLAB_DATABASE_ADAPTER` | `postgresql` (for MySQL use `mysql2`) | Yes +`GITLAB_DATABASE_DATABASE` | `gitlab_#{ENV['RAILS_ENV']` | Yes +`GITLAB_DATABASE_USERNAME` | `root` | Yes +`GITLAB_DATABASE_PASSWORD` | None | Yes +`GITLAB_DATABASE_HOST` | `localhost` | Yes +`GITLAB_DATABASE_PORT` | `5432` | Yes +`GITLAB_DATABASE_ENCODING` | `unicode` | No +`GITLAB_DATABASE_POOL` | `10` | No ## Adding more variables We welcome merge requests to make more settings configurable via variables. -Please make changes in the `config/initializers/1_settings.rb` file. -Please stick to the naming scheme `GITLAB_#{name in 1_settings.rb in upper case}`. +Please make changes in the `config/initializers/1_settings.rb` file and stick +to the naming scheme `GITLAB_#{name in 1_settings.rb in upper case}`. ## Omnibus configuration -It's possible to preconfigure the GitLab image by adding the environment variable: `GITLAB_OMNIBUS_CONFIG` to docker run command. +It's possible to preconfigure the GitLab docker image by adding the environment +variable `GITLAB_OMNIBUS_CONFIG` to the `docker run` command. For more information see the ['preconfigure-docker-container' section in the Omnibus documentation](http://doc.gitlab.com/omnibus/docker/#preconfigure-docker-container). From 9fbe9d97ed29288d065232687023edd74649d553 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 3 Feb 2016 14:18:51 +0200 Subject: [PATCH 68/89] Unicorn worker killer is not Omnibus specific [ci skip] --- doc/administration/environment_variables.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md index e49b3dc139..43ab153d76 100644 --- a/doc/administration/environment_variables.md +++ b/doc/administration/environment_variables.md @@ -20,8 +20,8 @@ Variable | Type | Description `GITLAB_EMAIL_FROM` | string | The e-mail address used in the "From" field in e-mails sent by GitLab `GITLAB_EMAIL_DISPLAY_NAME` | string | The name used in the "From" field in e-mails sent by GitLab `GITLAB_EMAIL_REPLY_TO` | string | The e-mail address used in the "Reply-To" field in e-mails sent by GitLab -`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer (supported only in Omnibus) -`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer (supported only in Omnibus) +`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer +`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer ## Complete database variables From 531767175f0a364a332c74bf27c5f202732ce519 Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Wed, 3 Feb 2016 09:21:37 -0500 Subject: [PATCH 69/89] Remove newrelic gem. Closes #12860 --- Gemfile | 2 -- Gemfile.lock | 2 -- config/newrelic.yml | 16 ---------------- 3 files changed, 20 deletions(-) delete mode 100644 config/newrelic.yml diff --git a/Gemfile b/Gemfile index 16a02da5bf..a8f3619782 100644 --- a/Gemfile +++ b/Gemfile @@ -303,8 +303,6 @@ group :production do gem "gitlab_meta", '7.0' end -gem "newrelic_rpm", '~> 3.14' - gem 'octokit', '~> 3.8.0' gem "mail_room", "~> 0.6.1" diff --git a/Gemfile.lock b/Gemfile.lock index 62937ab6fd..6dd8b56fe7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -479,7 +479,6 @@ GEM net-ldap (0.12.1) net-ssh (3.0.1) netrc (0.11.0) - newrelic_rpm (3.14.1.311) nokogiri (1.6.7.2) mini_portile2 (~> 2.0.0.rc2) nprogress-rails (0.1.6.7) @@ -960,7 +959,6 @@ DEPENDENCIES mysql2 (~> 0.3.16) nested_form (~> 0.3.2) net-ssh (~> 3.0.1) - newrelic_rpm (~> 3.14) nokogiri (= 1.6.7.2) nprogress-rails (~> 0.1.6.7) oauth2 (~> 1.0.0) diff --git a/config/newrelic.yml b/config/newrelic.yml deleted file mode 100644 index 9ef922a38d..0000000000 --- a/config/newrelic.yml +++ /dev/null @@ -1,16 +0,0 @@ -# New Relic configuration file -# -# This file is here to make sure the New Relic gem stays -# quiet by default. -# -# To enable and configure New Relic, please use -# environment variables, e.g. NEW_RELIC_ENABLED=true - -production: - enabled: false - -development: - enabled: false - -test: - enabled: false From 7aa739ddc720dcba42a2f54934b10f369d4cf566 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Wed, 20 Jan 2016 12:00:28 -0800 Subject: [PATCH 70/89] Support download access by PRIVATE-TOKEN header Currently there is no way to download a raw file without embedding the token in the URL, which exposes the token in the URL. There should be an way of sending this information via the header as the API does. Closes https://github.com/gitlabhq/gitlabhq/issues/8137 --- CHANGELOG | 1 + app/controllers/application_controller.rb | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7d7154487a..4c9b00084d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,7 @@ v 8.5.0 (unreleased) - Add "visibility" flag to GET /projects api endpoint - Ignore binary files in code search to prevent Error 500 (Stan Hu) - Render sanitized SVG images (Stan Hu) + - Support download access by PRIVATE-TOKEN header (Stan Hu) - Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push - New UI for pagination - Don't prevent sign out when 2FA enforcement is enabled and user hasn't yet diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 824175c8a6..7fa2f68ef0 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -60,6 +60,8 @@ class ApplicationController < ActionController::Base params[:authenticity_token].presence elsif params[:private_token].presence params[:private_token].presence + elsif request.headers['PRIVATE-TOKEN'].present? + request.headers['PRIVATE-TOKEN'] end user = user_token && User.find_by_authentication_token(user_token.to_s) From 639b25e34caa27191dc190c62b8d9ad59f9624ff Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 2 Feb 2016 23:31:46 +0100 Subject: [PATCH 71/89] Improve UI consistency between projects and groups lists Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + app/assets/stylesheets/pages/groups.scss | 20 +++++++++++++++++++- app/views/dashboard/_groups_head.html.haml | 20 +++++++++++++------- app/views/dashboard/groups/index.html.haml | 9 --------- app/views/shared/groups/_group.html.haml | 19 ++++++++++++++++--- 5 files changed, 49 insertions(+), 20 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7d7154487a..994e7a35b5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -25,6 +25,7 @@ v 8.5.0 (unreleased) - Deprecate API "merge_request/:merge_request_id/...". Use "merge_requests/:merge_request_id/..." instead - Mark inline difference between old and new paths when a file is renamed - Support Akismet spam checking for creation of issues via API (Stan Hu) + - Improve UI consistency between projects and groups lists v 8.4.3 - Increase lfs_objects size column to 8-byte integer to allow files larger diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss index fdd86979a3..ec6c099df5 100644 --- a/app/assets/stylesheets/pages/groups.scss +++ b/app/assets/stylesheets/pages/groups.scss @@ -4,7 +4,7 @@ input[type='search'] { width: 225px; vertical-align: bottom; - + @media (max-width: $screen-xs-max) { width: 100px; vertical-align: bottom; @@ -21,3 +21,21 @@ height: 42px; } } + +.group-row { + &.no-description { + .group-name { + line-height: 44px; + } + } + + .stats { + float: right; + line-height: 44px; + color: $gl-gray; + + span { + margin-right: 15px; + } + } +} diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml index 6ca97a692b..15e423a3b2 100644 --- a/app/views/dashboard/_groups_head.html.haml +++ b/app/views/dashboard/_groups_head.html.haml @@ -1,7 +1,13 @@ -%ul.nav-links - = nav_link(page: dashboard_groups_path) do - = link_to dashboard_groups_path, title: 'Your groups', data: {placement: 'right'} do - Your Groups - = nav_link(page: explore_groups_path) do - = link_to explore_groups_path, title: 'Explore groups', data: {placement: 'bottom'} do - Explore Groups +.top-area + %ul.nav-links + = nav_link(page: dashboard_groups_path) do + = link_to dashboard_groups_path, title: 'Your groups', data: {placement: 'right'} do + Your Groups + = nav_link(page: explore_groups_path) do + = link_to explore_groups_path, title: 'Explore groups', data: {placement: 'bottom'} do + Explore Groups + - if current_user.can_create_group? + .projects-search-form + = link_to new_group_path, class: "btn btn-new" do + = icon('plus') + New Group diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index d5b7e729e7..caca91af53 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -2,15 +2,6 @@ - header_title "Groups", dashboard_groups_path = render 'dashboard/groups_head' -.gray-content-block - - if current_user.can_create_group? - %span.pull-right.hidden-xs - = link_to new_group_path, class: "btn btn-new" do - %i.fa.fa-plus - New Group - .oneline - Group members have access to all group projects. - %ul.content-list - @group_members.each do |group_member| - group = group_member.group diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml index 778b20fb4f..aa2ece2248 100644 --- a/app/views/shared/groups/_group.html.haml +++ b/app/views/shared/groups/_group.html.haml @@ -1,5 +1,8 @@ - group_member = local_assigns[:group_member] -%li +- css_class = '' unless local_assigns[:css_class] +- css_class += " no-description" if group.description.blank? + +%li.group-row{ class: css_class } - if group_member .controls.hidden-xs - if can?(current_user, :admin_group, group) @@ -9,6 +12,15 @@ = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do %i.fa.fa-sign-out + .stats + %span + = icon('home') + = group.projects.count + + %span + = icon('users') + = group.users.count + = image_tag group_icon(group), class: "avatar s46 hidden-xs" = link_to group, class: 'group-name' do %span.item-title= group.name @@ -17,5 +29,6 @@ as %span #{group_member.human_access} - %div.light - #{pluralize(group.projects.count, "project")}, #{pluralize(group.users.count, "user")} + - if group.description.present? + .light + = markdown(group.description, pipeline: :description) From df922d811520f2b6459e84f1e595d3a0fcfc395c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 00:07:11 +0100 Subject: [PATCH 72/89] Add number_with_delimiter and remove unnecessary dara placement for groups page Signed-off-by: Dmitriy Zaporozhets --- app/views/dashboard/_groups_head.html.haml | 4 ++-- app/views/shared/groups/_group.html.haml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml index 15e423a3b2..e52070704d 100644 --- a/app/views/dashboard/_groups_head.html.haml +++ b/app/views/dashboard/_groups_head.html.haml @@ -1,10 +1,10 @@ .top-area %ul.nav-links = nav_link(page: dashboard_groups_path) do - = link_to dashboard_groups_path, title: 'Your groups', data: {placement: 'right'} do + = link_to dashboard_groups_path, title: 'Your groups' do Your Groups = nav_link(page: explore_groups_path) do - = link_to explore_groups_path, title: 'Explore groups', data: {placement: 'bottom'} do + = link_to explore_groups_path, title: 'Explore groups' do Explore Groups - if current_user.can_create_group? .projects-search-form diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml index aa2ece2248..f7fe6b0264 100644 --- a/app/views/shared/groups/_group.html.haml +++ b/app/views/shared/groups/_group.html.haml @@ -15,11 +15,11 @@ .stats %span = icon('home') - = group.projects.count + = number_with_delimiter(group.projects.count) %span = icon('users') - = group.users.count + = number_with_delimiter(group.users.count) = image_tag group_icon(group), class: "avatar s46 hidden-xs" = link_to group, class: 'group-name' do From 4beae990b37e3583485bb33f03e08e3cc798ff37 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 01:08:30 +0100 Subject: [PATCH 73/89] Refactor nav controls section (search and new project/group btn) Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/buttons.scss | 8 +- app/assets/stylesheets/framework/nav.scss | 62 +++++++++++++ app/assets/stylesheets/pages/projects.scss | 88 +------------------ app/views/dashboard/_groups_head.html.haml | 2 +- app/views/dashboard/_projects_head.html.haml | 6 +- app/views/groups/_projects.html.haml | 17 ++-- app/views/projects/forks/index.html.haml | 66 +++++++------- 7 files changed, 108 insertions(+), 141 deletions(-) diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index c99292c3f8..11df4c2405 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -82,8 +82,7 @@ &.btn-success, &.btn-new, &.btn-create, - &.btn-save, - &.btn-green { + &.btn-save { @include btn-green; } @@ -159,7 +158,6 @@ .input-group-btn { .btn { - @include btn-gray; @include btn-middle; &:hover { @@ -186,8 +184,4 @@ border: 1px solid #c6cacf !important; background-color: #e4e7ed !important; } - - .btn-green { - @include btn-green - } } diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index c537d97fb2..1d042dfb43 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -37,3 +37,65 @@ } } } + +.top-area { + border-bottom: 1px solid #EEE; + + .nav-text { + padding-top: 16px; + padding-bottom: 11px; + display: inline-block; + width: 50%; + line-height: 28px; + } + + .nav-links { + display: inline-block; + width: 50%; + margin-bottom: 0px; + border-bottom: none; + } + + .nav-controls { + width: 50%; + display: inline-block; + float: right; + text-align: right; + padding: 11px 0; + margin-bottom: 0px; + + > .dropdown { + display: inline-block; + } + + input { + display: inline-block; + width: calc(100% - 151px); + + /* Small devices (tablets, 768px and up) */ + @media (min-width: $screen-sm-min) { width: 150px; } + + /* Medium devices (desktops, 992px and up) */ + @media (min-width: $screen-md-min) { width: 200px; } + + /* Large devices (large desktops, 1200px and up) */ + @media (min-width: $screen-lg-min) { width: 300px; } + } + + .btn-new { + width: 135px; + margin-left: 10px; + float: right; + } + + .dropdown-toggle.btn { + margin-top: -3px; + } + } + + @media (max-width: $screen-xs-max) { + .nav-controls { + padding-top: 15px; + } + } +} diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index e4ea47cc4a..3d88746ddf 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -281,36 +281,6 @@ margin-top: -1px; } -.top-area { - border-bottom: 1px solid #EEE; - - ul.nav-links { - display: inline-block; - width: 50%; - margin-bottom: 0px; - border-bottom: none; - } - - .projects-search-form { - width: 50%; - display: inline-block; - float: right; - padding-top: 11px; - text-align: right; - - .btn-green { - margin-left: 10px; - float: right; - } - } - - @media (max-width: $screen-xs-max) { - .projects-search-form { - padding-top: 15px; - } - } -} - .fork-namespaces { .fork-thumbnail { text-align: center; @@ -386,22 +356,6 @@ pre.light-well { border-color: #f1f1f1; } -.projects-search-form { - padding: $gl-padding 0; - padding-bottom: 0; - margin-bottom: 0px; - - input { - display: inline-block; - width: calc(100% - 151px); - } - - .btn { - display: inline-block; - width: 135px; - } -} - .git-empty { margin: 0 7px 0 7px; @@ -559,52 +513,12 @@ pre.light-well { } } -.cannot-be-merged, +.cannot-be-merged, .cannot-be-merged:hover { color: #E62958; margin-top: 2px; } -/* - * Forks list rendered on Project's forks page - */ - -.forks-top-block { - padding: 16px 0; -} - -.projects-search-form { - .dropdown-toggle.btn { - margin-top: -3px; - } - - &.fork-search-form { - margin: 0; - margin-top: -$gl-padding; - padding-bottom: 0; - - input { - /* Small devices (tablets, 768px and up) */ - @media (min-width: $screen-sm-min) { width: 180px; } - - /* Medium devices (desktops, 992px and up) */ - @media (min-width: $screen-md-min) { width: 350px; } - - /* Large devices (large desktops, 1200px and up) */ - @media (min-width: $screen-lg-min) { width: 400px; } - } - - .sort-forks { - width: 160px; - } - - .fork-link { - float: right; - margin-left: $gl-padding; - } - } -} - .private-forks-notice .private-fork-icon { i:nth-child(1) { color: #2AA056; diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml index e52070704d..3d17f74b70 100644 --- a/app/views/dashboard/_groups_head.html.haml +++ b/app/views/dashboard/_groups_head.html.haml @@ -7,7 +7,7 @@ = link_to explore_groups_path, title: 'Explore groups' do Explore Groups - if current_user.can_create_group? - .projects-search-form + .nav-controls = link_to new_group_path, class: "btn btn-new" do = icon('plus') New Group diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index 5c4b58cd68..b6301f2238 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -12,9 +12,9 @@ = link_to explore_root_path, title: 'Explore', data: {placement: 'right'} do Explore Projects - .projects-search-form + .nav-controls = search_field_tag :filter_projects, nil, placeholder: 'Filter by name...', class: 'projects-list-filter form-control hidden-xs', spellcheck: false - if current_user.can_create_project? - = link_to new_project_path, class: 'btn btn-green' do - %i.fa.fa-plus + = link_to new_project_path, class: 'btn btn-new' do + = icon('plus') New Project diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index bbafc08435..a829479bb3 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -1,11 +1,10 @@ -.projects-list-holder - .projects-search-form - .input-group - = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false - - if can? current_user, :create_projects, @group - %span.input-group-btn - = link_to new_project_path(namespace_id: @group.id), class: 'btn btn-green' do - %i.fa.fa-plus - New Project +.projects-list-holder.prepend-top-default + .input-group + = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false + - if can? current_user, :create_projects, @group + %span.input-group-btn + = link_to new_project_path(namespace_id: @group.id), class: 'btn btn-new' do + = icon('plus') + New Project = render 'shared/projects/list', projects: @projects, projects_limit: 20, stars: false, skip_namespace: true diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml index a362185210..3fa7155bab 100644 --- a/app/views/projects/forks/index.html.haml +++ b/app/views/projects/forks/index.html.haml @@ -1,44 +1,42 @@ -.gray-content-block.top-block.clearfix.white.forks-top-block - .pull-left +.top-area + .nav-text - public_count = @public_forks.size - protected_count = @protected_forks.size - full_count_title = "#{public_count} public and #{protected_count} private" == #{pluralize(@all_forks.size, 'fork')}: #{full_count_title} - .pull-right - .projects-search-form.fork-search-form - = search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter form-control', - spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' } + .nav-controls + = search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter form-control', + spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' } - .dropdown.inline.prepend-left-10 - %button.dropdown-toggle.btn.sort-forks{type: 'button', 'data-toggle' => 'dropdown'} - %span.light sort: - - if @sort.present? - = sort_options_hash[@sort] - - else - = sort_title_recently_created - %b.caret - %ul.dropdown-menu.dropdown-menu-align-right - %li - - excluded_filters = [:state, :scope, :label_name, :milestone_id, :assignee_id, :author_id] - = link_to page_filter_path(sort: sort_value_recently_created, without: excluded_filters) do - = sort_title_recently_created - = link_to page_filter_path(sort: sort_value_oldest_created, without: excluded_filters) do - = sort_title_oldest_created - = link_to page_filter_path(sort: sort_value_recently_updated, without: excluded_filters) do - = sort_title_recently_updated - = link_to page_filter_path(sort: sort_value_oldest_updated, without: excluded_filters) do - = sort_title_oldest_updated - - .fork-link.inline - - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 - = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'pull-right btn btn-new' do - = icon('code-fork fw') - Fork + .dropdown.prepend-left-10 + %button.dropdown-toggle.btn.sort-forks{type: 'button', 'data-toggle' => 'dropdown'} + %span.light sort: + - if @sort.present? + = sort_options_hash[@sort] - else - = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'pull-right btn btn-new' do - = icon('code-fork fw') - Fork + = sort_title_recently_created + %b.caret + %ul.dropdown-menu.dropdown-menu-align-right + %li + - excluded_filters = [:state, :scope, :label_name, :milestone_id, :assignee_id, :author_id] + = link_to page_filter_path(sort: sort_value_recently_created, without: excluded_filters) do + = sort_title_recently_created + = link_to page_filter_path(sort: sort_value_oldest_created, without: excluded_filters) do + = sort_title_oldest_created + = link_to page_filter_path(sort: sort_value_recently_updated, without: excluded_filters) do + = sort_title_recently_updated + = link_to page_filter_path(sort: sort_value_oldest_updated, without: excluded_filters) do + = sort_title_oldest_updated + + - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 + = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-new' do + = icon('code-fork fw') + Fork + - else + = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn btn-new' do + = icon('code-fork fw') + Fork .projects-list-holder From ad5acec6e5aa1376e5711cdac531db8f9cca3d01 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 01:50:53 +0100 Subject: [PATCH 74/89] Make nav-controls responsive and hide on extra small screens Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/nav.scss | 54 +++++++++++++++++------ app/views/projects/forks/index.html.haml | 4 +- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 1d042dfb43..6410656847 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -39,6 +39,8 @@ } .top-area { + @include clearfix; + border-bottom: 1px solid #EEE; .nav-text { @@ -47,6 +49,11 @@ display: inline-block; width: 50%; line-height: 28px; + + /* Small devices (phones, tablets, 768px and lower) */ + @media (max-width: $screen-sm-min) { + width: 100%; + } } .nav-links { @@ -54,6 +61,11 @@ width: 50%; margin-bottom: 0px; border-bottom: none; + + /* Small devices (phones, tablets, 768px and lower) */ + @media (max-width: $screen-sm-min) { + width: 100%; + } } .nav-controls { @@ -65,37 +77,51 @@ margin-bottom: 0px; > .dropdown { + margin-left: 10px; display: inline-block; } + > .btn { + display: inline-block; + margin-left: 10px; + margin-top: -3px; + } + input { display: inline-block; - width: calc(100% - 151px); - - /* Small devices (tablets, 768px and up) */ - @media (min-width: $screen-sm-min) { width: 150px; } /* Medium devices (desktops, 992px and up) */ @media (min-width: $screen-md-min) { width: 200px; } /* Large devices (large desktops, 1200px and up) */ - @media (min-width: $screen-lg-min) { width: 300px; } - } + @media (min-width: $screen-lg-min) { width: 250px; } - .btn-new { - width: 135px; - margin-left: 10px; - float: right; + &.input-short { + /* Medium devices (desktops, 992px and up) */ + @media (min-width: $screen-md-min) { width: 170px; } + + /* Large devices (large desktops, 1200px and up) */ + @media (min-width: $screen-lg-min) { width: 210px; } + } } .dropdown-toggle.btn { margin-top: -3px; } - } - @media (max-width: $screen-xs-max) { - .nav-controls { - padding-top: 15px; + /* Hide on extra small devices (phones) */ + @media (max-width: $screen-xs-max) { + display: none; + } + + /* Small devices (tablets, 768px and lower) */ + @media (max-width: $screen-sm-max) { + width: 100%; + text-align: left; + + input { + width: 300px; + } } } } diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml index 3fa7155bab..acb2353d3c 100644 --- a/app/views/projects/forks/index.html.haml +++ b/app/views/projects/forks/index.html.haml @@ -6,10 +6,10 @@ == #{pluralize(@all_forks.size, 'fork')}: #{full_count_title} .nav-controls - = search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter form-control', + = search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter form-control input-short', spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' } - .dropdown.prepend-left-10 + .dropdown %button.dropdown-toggle.btn.sort-forks{type: 'button', 'data-toggle' => 'dropdown'} %span.light sort: - if @sort.present? From faacb7853478704a37655361c23abffdfd47db6f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 02:01:33 +0100 Subject: [PATCH 75/89] Tried to align form input vertically with other elements for top nav Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/nav.scss | 8 +++----- app/views/dashboard/_projects_head.html.haml | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 6410656847..252f84a6b4 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -84,11 +84,13 @@ > .btn { display: inline-block; margin-left: 10px; - margin-top: -3px; } input { + height: 34px; display: inline-block; + position: relative; + top: 1px; /* Medium devices (desktops, 992px and up) */ @media (min-width: $screen-md-min) { width: 200px; } @@ -105,10 +107,6 @@ } } - .dropdown-toggle.btn { - margin-top: -3px; - } - /* Hide on extra small devices (phones) */ @media (max-width: $screen-xs-max) { display: none; diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index b6301f2238..726f669b1d 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -8,7 +8,7 @@ = nav_link(page: starred_dashboard_projects_path) do = link_to starred_dashboard_projects_path, title: 'Starred Projects', data: {placement: 'right'} do Starred Projects - = nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path], html_options: { class: 'hidden-xs' }) do + = nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path]) do = link_to explore_root_path, title: 'Explore', data: {placement: 'right'} do Explore Projects From 754538b99206a778ddf87e0d362fccb0ff2f6c15 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 02:10:33 +0100 Subject: [PATCH 76/89] Use right margin for componened other than button for top nav Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/nav.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 252f84a6b4..e6c59f5a29 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -77,13 +77,12 @@ margin-bottom: 0px; > .dropdown { - margin-left: 10px; + margin-right: 10px; display: inline-block; } > .btn { display: inline-block; - margin-left: 10px; } input { @@ -91,6 +90,7 @@ display: inline-block; position: relative; top: 1px; + margin-right: 10px; /* Medium devices (desktops, 992px and up) */ @media (min-width: $screen-md-min) { width: 200px; } From ea7bdc78eed8db7ff4b5440b282678b1c5b021f7 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Wed, 3 Feb 2016 11:17:14 -0500 Subject: [PATCH 77/89] Updated omniuath-saml to the latest version. --- Gemfile | 2 +- Gemfile.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index 16a02da5bf..a06dbe8e06 100644 --- a/Gemfile +++ b/Gemfile @@ -30,7 +30,7 @@ gem 'omniauth-github', '~> 1.1.1' gem 'omniauth-gitlab', '~> 1.0.0' gem 'omniauth-google-oauth2', '~> 0.2.0' gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos -gem 'omniauth-saml', '~> 1.4.0' +gem 'omniauth-saml', '~> 1.4.2' gem 'omniauth-shibboleth', '~> 1.2.0' gem 'omniauth-twitter', '~> 1.2.0' gem 'omniauth_crowd', '~> 2.2.0' diff --git a/Gemfile.lock b/Gemfile.lock index 62937ab6fd..bd76701610 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -532,9 +532,9 @@ GEM omniauth-oauth2 (1.3.1) oauth2 (~> 1.0) omniauth (~> 1.2) - omniauth-saml (1.4.1) + omniauth-saml (1.4.2) omniauth (~> 1.1) - ruby-saml (~> 1.0.0) + ruby-saml (~> 1.1, >= 1.1.1) omniauth-shibboleth (1.2.1) omniauth (>= 1.0.0) omniauth-twitter (1.2.1) @@ -690,7 +690,7 @@ GEM ruby-fogbugz (0.2.1) crack (~> 0.4) ruby-progressbar (1.7.5) - ruby-saml (1.0.0) + ruby-saml (1.1.1) nokogiri (>= 1.5.10) uuid (~> 2.3) ruby2ruby (2.2.0) @@ -974,7 +974,7 @@ DEPENDENCIES omniauth-gitlab (~> 1.0.0) omniauth-google-oauth2 (~> 0.2.0) omniauth-kerberos (~> 0.3.0) - omniauth-saml (~> 1.4.0) + omniauth-saml (~> 1.4.2) omniauth-shibboleth (~> 1.2.0) omniauth-twitter (~> 1.2.0) omniauth_crowd (~> 2.2.0) From 6f8ae85567a360deafc6390e2a9ada6513a89fa3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 18:05:58 +0100 Subject: [PATCH 78/89] Fix missing space between fork and star icons Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/pages/projects.scss | 4 ++++ app/views/shared/projects/_project.html.haml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 3d88746ddf..dd4ff39c5b 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -415,6 +415,10 @@ pre.light-well { a:hover { text-decoration: none; } + + > span { + margin-left: 10px; + } } .project-description { diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml index 2aeeed63c9..e196fc51d2 100644 --- a/app/views/shared/projects/_project.html.haml +++ b/app/views/shared/projects/_project.html.haml @@ -29,8 +29,8 @@ .project-controls - if ci_commit - = render_ci_status(ci_commit) -   + %span + = render_ci_status(ci_commit) - if forks %span = icon('code-fork') From 8cd25901d3de83d7d03c33361a61308effa13760 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 18:41:55 +0100 Subject: [PATCH 79/89] Use top-area component for top page navigation for pages that contains list of items Signed-off-by: Dmitriy Zaporozhets --- .../dashboard/milestones/index.html.haml | 8 +++---- app/views/groups/milestones/index.html.haml | 16 ++++++------- app/views/help/ui.html.haml | 24 +++++++++++++++++++ app/views/projects/builds/index.html.haml | 23 +++++++++--------- app/views/projects/labels/index.html.haml | 13 +++++----- app/views/projects/milestones/index.html.haml | 14 +++++------ app/views/projects/wikis/_nav.html.haml | 18 +++++++------- app/views/shared/_milestones_filter.html.haml | 21 ++++++++-------- 8 files changed, 79 insertions(+), 58 deletions(-) diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml index bec1692a4d..2ee167db91 100644 --- a/app/views/dashboard/milestones/index.html.haml +++ b/app/views/dashboard/milestones/index.html.haml @@ -1,12 +1,12 @@ - page_title "Milestones" - header_title "Milestones", dashboard_milestones_path -.project-issuable-filter - .controls - = render 'shared/new_project_item_select', path: 'milestones/new', label: "New Milestone", include_groups: true - +.top-area = render 'shared/milestones_filter' + .nav-controls + = render 'shared/new_project_item_select', path: 'milestones/new', label: "New Milestone", include_groups: true + .gray-content-block List all milestones from all projects you have access to. diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index b221d3a89a..ab307708b7 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -1,17 +1,15 @@ - page_title "Milestones" - header_title group_title(@group, "Milestones", group_milestones_path(@group)) -.project-issuable-filter - .controls - - if can?(current_user, :admin_milestones, @group) - .pull-right - %span.pull-right.hidden-xs - = link_to new_group_milestone_path(@group), class: "btn btn-new" do - = icon('plus') - New Milestone - +.top-area = render 'shared/milestones_filter' + .nav-controls + - if can?(current_user, :admin_milestones, @group) + = link_to new_group_milestone_path(@group), class: "btn btn-new" do + = icon('plus') + New Milestone + .gray-content-block Only milestones from %strong #{@group.name} diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml index 7b45bd0905..746386cab5 100644 --- a/app/views/help/ui.html.haml +++ b/app/views/help/ui.html.haml @@ -138,8 +138,32 @@ %h2#navs Navigation + %h4 + %code .top-area + %p Holder for top page navigation. Includes navigation, search field, sorting and button + + .example + .top-area + %ul.nav-links + %li.active + %a Open + %li + %a Closed + .nav-controls + = text_field_tag 'sample', nil, class: 'form-control' + .dropdown + %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} + %span Sort by name + %b.caret + %ul.dropdown-menu + %li + %a Sort by date + + = link_to 'New issue', '#', class: 'btn btn-new' + %h4 %code .nav-links + %p Only nav links without button and search .example %ul.nav-links %li.active diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml index bbb6944a65..630d0286f2 100644 --- a/app/views/projects/builds/index.html.haml +++ b/app/views/projects/builds/index.html.haml @@ -1,18 +1,7 @@ - page_title "Builds" = render "header_title" -.project-issuable-filter - .controls - - if can?(current_user, :manage_builds, @project) - .pull-left.hidden-xs - - if @all_builds.running_or_pending.any? - = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), - data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post - - = link_to ci_lint_path, class: 'btn btn-default' do - = icon('wrench') - %span CI Lint - +.top-area %ul.nav-links %li{class: ('active' if @scope.nil?)} = link_to project_builds_path(@project) do @@ -32,6 +21,16 @@ %span.badge.js-running-count = number_with_delimiter(@all_builds.finished.count(:id)) + .nav-controls + - if can?(current_user, :manage_builds, @project) + - if @all_builds.running_or_pending.any? + = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), + data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post + + = link_to ci_lint_path, class: 'btn btn-default' do + = icon('wrench') + %span CI Lint + .gray-content-block #{(@scope || 'running').capitalize} builds from this project diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index 9081bcfe9b..cc41130a9d 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -1,13 +1,14 @@ - page_title "Labels" = render "header_title" -.gray-content-block.top-block - - if can? current_user, :admin_label, @project - = link_to new_namespace_project_label_path(@project.namespace, @project), class: "pull-right btn btn-new" do - = icon('plus') - New label - .oneline +.top-area + .nav-text Labels can be applied to issues and merge requests. + .nav-controls + - if can? current_user, :admin_label, @project + = link_to new_namespace_project_label_path(@project.namespace, @project), class: "btn btn-new" do + = icon('plus') + New label .labels - if @labels.present? diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index 114b06457a..49625b3534 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -2,15 +2,15 @@ = render "header_title" -.project-issuable-filter - .controls - - if can?(current_user, :admin_milestone, @project) - = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "pull-right btn btn-new", title: "New Milestone" do - %i.fa.fa-plus - New Milestone - +.top-area = render 'shared/milestones_filter' + .nav-controls + - if can?(current_user, :admin_milestone, @project) + = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "btn btn-new", title: "New Milestone" do + = icon('plus') + New Milestone + .gray-content-block Milestone allows you to group issues and set due date for it diff --git a/app/views/projects/wikis/_nav.html.haml b/app/views/projects/wikis/_nav.html.haml index 69ba301e23..56a53ffff2 100644 --- a/app/views/projects/wikis/_nav.html.haml +++ b/app/views/projects/wikis/_nav.html.haml @@ -1,12 +1,4 @@ -.project-issuable-filter - .controls - - if can?(current_user, :create_wiki, @project) - = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do - %i.fa.fa-plus - New Page - - = render 'projects/wikis/new' - +.top-area %ul.nav-links = nav_link(html_options: {class: params[:id] == 'home' ? 'active' : '' }) do = link_to 'Home', namespace_project_wiki_path(@project.namespace, @project, :home) @@ -17,3 +9,11 @@ = nav_link(path: 'wikis#git_access') do = link_to namespace_project_wikis_git_access_path(@project.namespace, @project) do Git Access + + .nav-controls + - if can?(current_user, :create_wiki, @project) + = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do + = icon('plus') + New Page + + = render 'projects/wikis/new' diff --git a/app/views/shared/_milestones_filter.html.haml b/app/views/shared/_milestones_filter.html.haml index f77feeb79c..cf16c203f9 100644 --- a/app/views/shared/_milestones_filter.html.haml +++ b/app/views/shared/_milestones_filter.html.haml @@ -1,11 +1,10 @@ -.milestones-filters - %ul.nav-links - %li{class: ("active" if params[:state].blank? || params[:state] == 'opened')} - = link_to milestones_filter_path(state: 'opened') do - Open - %li{class: ("active" if params[:state] == 'closed')} - = link_to milestones_filter_path(state: 'closed') do - Closed - %li{class: ("active" if params[:state] == 'all')} - = link_to milestones_filter_path(state: 'all') do - All +%ul.nav-links + %li{class: ("active" if params[:state].blank? || params[:state] == 'opened')} + = link_to milestones_filter_path(state: 'opened') do + Open + %li{class: ("active" if params[:state] == 'closed')} + = link_to milestones_filter_path(state: 'closed') do + Closed + %li{class: ("active" if params[:state] == 'all')} + = link_to milestones_filter_path(state: 'all') do + All From a441658783c5cdcda64f4cbd55ffabe24b646b46 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 18:51:52 +0100 Subject: [PATCH 80/89] Remove useless text tips on commonly used pages Signed-off-by: Dmitriy Zaporozhets --- app/views/dashboard/issues.html.haml | 3 --- app/views/dashboard/merge_requests.html.haml | 3 --- app/views/dashboard/milestones/index.html.haml | 3 --- app/views/projects/milestones/index.html.haml | 3 --- 4 files changed, 12 deletions(-) diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index 2d3da01178..f363f03597 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -16,8 +16,5 @@ = render 'shared/issuable/filter', type: :issues -.gray-content-block.second-block - List all issues from all projects you have access to. - .prepend-top-default = render 'shared/issues' diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index c5a5ec21f7..bbe4cc1f82 100644 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -7,8 +7,5 @@ = render 'shared/issuable/filter', type: :merge_requests -.gray-content-block.second-block - List all merge requests from all projects you have access to. - .prepend-top-default = render 'shared/merge_requests' diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml index bec1692a4d..eb2979fc13 100644 --- a/app/views/dashboard/milestones/index.html.haml +++ b/app/views/dashboard/milestones/index.html.haml @@ -7,9 +7,6 @@ = render 'shared/milestones_filter' -.gray-content-block - List all milestones from all projects you have access to. - .milestones %ul.content-list - if @milestones.blank? diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index 114b06457a..aa185126b5 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -11,9 +11,6 @@ = render 'shared/milestones_filter' -.gray-content-block - Milestone allows you to group issues and set due date for it - .milestones %ul.content-list = render @milestones From 73bd729ecca27a293c47101dd399e628e221ce2d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 20:13:26 +0100 Subject: [PATCH 81/89] Add sort dropdown to dashboard projects page Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + app/assets/stylesheets/pages/explore.scss | 8 -------- app/controllers/dashboard/projects_controller.rb | 1 + app/helpers/explore_helper.rb | 13 ++++++++++++- app/views/dashboard/_projects_head.html.haml | 3 ++- app/views/explore/projects/_dropdown.html.haml | 12 +++--------- app/views/explore/projects/_filter.html.haml | 2 +- app/views/explore/projects/_nav.html.haml | 10 ++++++++++ app/views/explore/projects/index.html.haml | 6 +++++- app/views/explore/projects/starred.html.haml | 12 +++--------- app/views/explore/projects/trending.html.haml | 10 ++-------- 11 files changed, 40 insertions(+), 38 deletions(-) create mode 100644 app/views/explore/projects/_nav.html.haml diff --git a/CHANGELOG b/CHANGELOG index 5f081236c1..481a0f8d24 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -27,6 +27,7 @@ v 8.5.0 (unreleased) - Mark inline difference between old and new paths when a file is renamed - Support Akismet spam checking for creation of issues via API (Stan Hu) - Improve UI consistency between projects and groups lists + - Add sort dropdown to dashboard projects page v 8.4.3 - Increase lfs_objects size column to 8-byte integer to allow files larger diff --git a/app/assets/stylesheets/pages/explore.scss b/app/assets/stylesheets/pages/explore.scss index da06fe9954..9b92128624 100644 --- a/app/assets/stylesheets/pages/explore.scss +++ b/app/assets/stylesheets/pages/explore.scss @@ -6,11 +6,3 @@ font-size: 30px; } } - -.explore-trending-block { - .lead { - line-height: 32px; - font-size: 18px; - margin-top: 10px; - } -} diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index 0b7fcdf5e9..721e2a6bcb 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -3,6 +3,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController def index @projects = current_user.authorized_projects.sorted_by_activity.non_archived + @projects = @projects.sort(@sort = params[:sort]) @projects = @projects.includes(:namespace) @last_push = current_user.recent_push diff --git a/app/helpers/explore_helper.rb b/app/helpers/explore_helper.rb index 0d291f9a87..3648757428 100644 --- a/app/helpers/explore_helper.rb +++ b/app/helpers/explore_helper.rb @@ -10,8 +10,19 @@ module ExploreHelper options = exist_opts.merge(options) - path = explore_projects_path + path = if explore_controller? + explore_projects_path + elsif current_action?(:starred) + starred_dashboard_projects_path + else + dashboard_projects_path + end + path << "?#{options.to_param}" path end + + def explore_controller? + controller.class.name.split("::").first == "Explore" + end end diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index 726f669b1d..d865a2c6fa 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -13,7 +13,8 @@ Explore Projects .nav-controls - = search_field_tag :filter_projects, nil, placeholder: 'Filter by name...', class: 'projects-list-filter form-control hidden-xs', spellcheck: false + = search_field_tag :filter_projects, nil, placeholder: 'Filter by name...', class: 'projects-list-filter form-control hidden-xs input-short', spellcheck: false + = render 'explore/projects/dropdown' - if current_user.can_create_project? = link_to new_project_path, class: 'btn btn-new' do = icon('plus') diff --git a/app/views/explore/projects/_dropdown.html.haml b/app/views/explore/projects/_dropdown.html.haml index a988d4c815..87c556adc7 100644 --- a/app/views/explore/projects/_dropdown.html.haml +++ b/app/views/explore/projects/_dropdown.html.haml @@ -3,19 +3,13 @@ %span.light - if @sort.present? = sort_options_hash[@sort] - - elsif current_page?(trending_explore_projects_path) || current_page?(explore_root_path) - Trending projects - - elsif current_page?(starred_explore_projects_path) - Most stars - else - = sort_title_recently_created + = sort_title_recently_updated %b.caret %ul.dropdown-menu %li - = link_to trending_explore_projects_path do - Trending projects - = link_to starred_explore_projects_path do - Most stars + = link_to explore_projects_filter_path(sort: sort_value_name) do + = sort_title_name = link_to explore_projects_filter_path(sort: sort_value_recently_created) do = sort_title_recently_created = link_to explore_projects_filter_path(sort: sort_value_oldest_created) do diff --git a/app/views/explore/projects/_filter.html.haml b/app/views/explore/projects/_filter.html.haml index 28b12c8dca..66a4b535ae 100644 --- a/app/views/explore/projects/_filter.html.haml +++ b/app/views/explore/projects/_filter.html.haml @@ -2,6 +2,7 @@ = form_tag explore_projects_filter_path, method: :get, class: 'form-inline form-tiny' do |f| .form-group = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "projects_search", spellcheck: false + = hidden_field_tag :sort, @sort .form-group = button_tag 'Search', class: "btn" @@ -46,4 +47,3 @@ = link_to explore_projects_filter_path(tag: tag.name) do %i.fa.fa-tag = tag.name - = render 'explore/projects/dropdown' diff --git a/app/views/explore/projects/_nav.html.haml b/app/views/explore/projects/_nav.html.haml new file mode 100644 index 0000000000..614b543177 --- /dev/null +++ b/app/views/explore/projects/_nav.html.haml @@ -0,0 +1,10 @@ +%ul.nav-links + = nav_link(page: [trending_explore_projects_path, explore_root_path]) do + = link_to trending_explore_projects_path do + Trending + = nav_link(page: starred_explore_projects_path) do + = link_to starred_explore_projects_path do + Most stars + = nav_link(page: explore_projects_path) do + = link_to explore_projects_path do + All diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml index b9a958fbe7..bee8518d57 100644 --- a/app/views/explore/projects/index.html.haml +++ b/app/views/explore/projects/index.html.haml @@ -6,7 +6,11 @@ - else = render 'explore/head' -.gray-content-block.clearfix.second-block +.top-area + = render 'explore/projects/nav' + +.gray-content-block.second-block.clearfix = render 'filter' + = render 'projects', projects: @projects = paginate @projects, theme: "gitlab" diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index 95d46e331f..16f52f7a53 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -6,12 +6,6 @@ - else = render 'explore/head' -.explore-trending-block - .gray-content-block.second-block - .pull-right - = render 'explore/projects/dropdown' - .oneline - %i.fa.fa-star - See most starred projects - = render 'projects', projects: @starred_projects - = paginate @starred_projects, theme: 'gitlab' += render 'explore/projects/nav' += render 'projects', projects: @starred_projects += paginate @starred_projects, theme: 'gitlab' diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml index fa0b718e48..adcda81006 100644 --- a/app/views/explore/projects/trending.html.haml +++ b/app/views/explore/projects/trending.html.haml @@ -6,11 +6,5 @@ - else = render 'explore/head' -.explore-trending-block - .gray-content-block.second-block - .pull-right - = render 'explore/projects/dropdown' - .oneline - %i.fa.fa-comments-o - See most discussed projects for last month - = render 'projects', projects: @trending_projects += render 'explore/projects/nav' += render 'projects', projects: @trending_projects From f8a33707b7b0626c5f8e22289197d2054e86d918 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 20:21:26 +0100 Subject: [PATCH 82/89] Fix tests Signed-off-by: Dmitriy Zaporozhets --- spec/features/builds_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/features/builds_spec.rb b/spec/features/builds_spec.rb index d37bd10371..5b6f3cb3f1 100644 --- a/spec/features/builds_spec.rb +++ b/spec/features/builds_spec.rb @@ -18,7 +18,7 @@ describe "Builds" do visit namespace_project_builds_path(@project.namespace, @project, scope: :running) end - it { expect(page).to have_selector('.project-issuable-filter li.active', text: 'Running') } + it { expect(page).to have_selector('.nav-links li.active', text: 'Running') } it { expect(page).to have_link 'Cancel running' } it { expect(page).to have_content @build.short_sha } it { expect(page).to have_content @build.ref } @@ -31,7 +31,7 @@ describe "Builds" do visit namespace_project_builds_path(@project.namespace, @project, scope: :finished) end - it { expect(page).to have_selector('.project-issuable-filter li.active', text: 'Finished') } + it { expect(page).to have_selector('.nav-links li.active', text: 'Finished') } it { expect(page).to have_content 'No builds to show' } it { expect(page).to have_link 'Cancel running' } end @@ -42,7 +42,7 @@ describe "Builds" do visit namespace_project_builds_path(@project.namespace, @project) end - it { expect(page).to have_selector('.project-issuable-filter li.active', text: 'All') } + it { expect(page).to have_selector('.nav-links li.active', text: 'All') } it { expect(page).to have_content @build.short_sha } it { expect(page).to have_content @build.ref } it { expect(page).to have_content @build.name } @@ -57,7 +57,7 @@ describe "Builds" do click_link "Cancel running" end - it { expect(page).to have_selector('.project-issuable-filter li.active', text: 'All') } + it { expect(page).to have_selector('.nav-links li.active', text: 'All') } it { expect(page).to have_content 'canceled' } it { expect(page).to have_content @build.short_sha } it { expect(page).to have_content @build.ref } From ccd99efe64b546a0f5e6bd774479cde2861287ef Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 22:48:21 +0100 Subject: [PATCH 83/89] Update test after changes build page css Signed-off-by: Dmitriy Zaporozhets --- features/steps/project/builds/summary.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/project/builds/summary.rb b/features/steps/project/builds/summary.rb index 036bc0a499..4bc670fdfc 100644 --- a/features/steps/project/builds/summary.rb +++ b/features/steps/project/builds/summary.rb @@ -13,7 +13,7 @@ class Spinach::Features::ProjectBuildsSummary < Spinach::FeatureSteps end step 'I see button to CI Lint' do - page.within('.controls') do + page.within('.nav-controls') do ci_lint_tool_link = page.find_link('CI Lint') expect(ci_lint_tool_link[:href]).to eq ci_lint_path end From 47982e50c4038ed6e56b1dd28b4d4888b33460eb Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 3 Feb 2016 17:19:54 -0500 Subject: [PATCH 84/89] Make Pipelines responsible for defining their custom whitelist This allows for future pipelines to more easily define a custom whitelist. --- lib/banzai/filter/sanitization_filter.rb | 9 +---- lib/banzai/pipeline/description_pipeline.rb | 13 ++++++- .../banzai/filter/sanitization_filter_spec.rb | 22 ----------- .../pipeline/description_pipeline_spec.rb | 37 +++++++++++++++++++ 4 files changed, 50 insertions(+), 31 deletions(-) create mode 100644 spec/lib/banzai/pipeline/description_pipeline_spec.rb diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb index d1e11eedec..04ddfe53ed 100644 --- a/lib/banzai/filter/sanitization_filter.rb +++ b/lib/banzai/filter/sanitization_filter.rb @@ -8,14 +8,7 @@ module Banzai # Extends HTML::Pipeline::SanitizationFilter with a custom whitelist. class SanitizationFilter < HTML::Pipeline::SanitizationFilter def whitelist - # Descriptions are more heavily sanitized, allowing only a few elements. - # See http://git.io/vkuAN - if context[:inline_sanitization] - whitelist = LIMITED - whitelist[:elements] -= %w(pre code img ol ul li) - else - whitelist = super - end + whitelist = super customize_whitelist(whitelist) diff --git a/lib/banzai/pipeline/description_pipeline.rb b/lib/banzai/pipeline/description_pipeline.rb index 20e24ace35..f239586765 100644 --- a/lib/banzai/pipeline/description_pipeline.rb +++ b/lib/banzai/pipeline/description_pipeline.rb @@ -4,9 +4,20 @@ module Banzai def self.transform_context(context) super(context).merge( # SanitizationFilter - inline_sanitization: true + whitelist: whitelist ) end + + private + + def self.whitelist + # Descriptions are more heavily sanitized, allowing only a few elements. + # See http://git.io/vkuAN + whitelist = Banzai::Filter::SanitizationFilter::LIMITED + whitelist[:elements] -= %w(pre code img ol ul li) + + whitelist + end end end end diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb index 9c63d22704..e14a6dbf92 100644 --- a/spec/lib/banzai/filter/sanitization_filter_spec.rb +++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb @@ -177,26 +177,4 @@ describe Banzai::Filter::SanitizationFilter, lib: true do expect(act.to_html).to eq exp end end - - context 'when inline_sanitization is true' do - it 'uses a stricter whitelist' do - doc = filter('

Description

', inline_sanitization: true) - expect(doc.to_html.strip).to eq 'Description' - end - - %w(pre code img ol ul li).each do |elem| - it "removes '#{elem}' elements" do - act = "<#{elem}>Description" - expect(filter(act, inline_sanitization: true).to_html.strip). - to eq 'Description' - end - end - - %w(b i strong em a ins del sup sub p).each do |elem| - it "still allows '#{elem}' elements" do - exp = act = "<#{elem}>Description" - expect(filter(act, inline_sanitization: true).to_html).to eq exp - end - end - end end diff --git a/spec/lib/banzai/pipeline/description_pipeline_spec.rb b/spec/lib/banzai/pipeline/description_pipeline_spec.rb new file mode 100644 index 0000000000..76f4207181 --- /dev/null +++ b/spec/lib/banzai/pipeline/description_pipeline_spec.rb @@ -0,0 +1,37 @@ +require 'rails_helper' + +describe Banzai::Pipeline::DescriptionPipeline do + def parse(html) + # When we pass HTML to Redcarpet, it gets wrapped in `p` tags... + # ...except when we pass it pre-wrapped text. Rabble rabble. + unwrap = !html.start_with?('

') + + output = described_class.to_html(html, project: spy) + + output.gsub!(%r{\A

(.*)

(.*)\z}, '\1\2') if unwrap + + output + end + + it 'uses a limited whitelist' do + doc = parse('# Description') + + expect(doc.strip).to eq 'Description' + end + + %w(pre code img ol ul li).each do |elem| + it "removes '#{elem}' elements" do + act = "<#{elem}>Description" + + expect(parse(act).strip).to eq 'Description' + end + end + + %w(b i strong em a ins del sup sub p).each do |elem| + it "still allows '#{elem}' elements" do + exp = act = "<#{elem}>Description" + + expect(parse(act).strip).to eq exp + end + end +end From de6f2884eaf096ff16062aa1fb3f8e518b69c2b5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 23:27:00 +0100 Subject: [PATCH 85/89] Sort projects by last activity for project switcher in header Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/api.js.coffee | 3 ++- app/assets/javascripts/project_select.js.coffee | 3 ++- app/helpers/projects_helper.rb | 5 ++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/api.js.coffee b/app/assets/javascripts/api.js.coffee index 746fa3cea8..3e0fdb3f79 100644 --- a/app/assets/javascripts/api.js.coffee +++ b/app/assets/javascripts/api.js.coffee @@ -47,7 +47,7 @@ callback(namespaces) # Return projects list. Filtered by query - projects: (query, callback) -> + projects: (query, order, callback) -> url = Api.buildUrl(Api.projects_path) $.ajax( @@ -55,6 +55,7 @@ data: private_token: gon.api_token search: query + order_by: order per_page: 20 dataType: "json" ).done (projects) -> diff --git a/app/assets/javascripts/project_select.js.coffee b/app/assets/javascripts/project_select.js.coffee index 0ae274f336..be8ab9b428 100644 --- a/app/assets/javascripts/project_select.js.coffee +++ b/app/assets/javascripts/project_select.js.coffee @@ -3,6 +3,7 @@ class @ProjectSelect $('.ajax-project-select').each (i, select) -> @groupId = $(select).data('group-id') @includeGroups = $(select).data('include-groups') + @orderBy = $(select).data('order-by') || 'id' placeholder = "Search for project" placeholder += " or group" if @includeGroups @@ -28,7 +29,7 @@ class @ProjectSelect if @groupId Api.groupProjects @groupId, query.term, projectsCallback else - Api.projects query.term, projectsCallback + Api.projects query.term, @orderBy, projectsCallback id: (project) -> project.web_url diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index e7e472cbb5..0aaa677429 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -57,7 +57,10 @@ module ProjectsHelper link_output = simple_sanitize(project.name) link_output += content_tag :span, nil, { class: "fa fa-chevron-down dropdown-toggle-caret" } if current_user - link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", data: { include_groups: false } if current_user + if current_user + link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", + data: { include_groups: false, order_by: 'last_activity_at' } + end link_output end From 9f8acf8a8378741d00ed1f665c0f5f692057ac8d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 4 Feb 2016 09:57:17 +0100 Subject: [PATCH 86/89] Satisfy rubocop Signed-off-by: Dmitriy Zaporozhets --- app/helpers/projects_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 0aaa677429..dc487a31d9 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -58,7 +58,8 @@ module ProjectsHelper link_output += content_tag :span, nil, { class: "fa fa-chevron-down dropdown-toggle-caret" } if current_user if current_user - link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", + link_output += project_select_tag :project_path, + class: "project-item-select js-projects-dropdown", data: { include_groups: false, order_by: 'last_activity_at' } end From c6e0228ca9937b10ad8e2620501d4fe221108d9a Mon Sep 17 00:00:00 2001 From: Zeger-Jan van de Weg Date: Thu, 4 Feb 2016 11:51:12 +0100 Subject: [PATCH 87/89] Hide remove source branch button when new commit is added to branch Fixes #3339 This MR hides the 'Remove source branch' button when a new commit is added to the source branch --- CHANGELOG | 1 + app/models/merge_request.rb | 3 ++- spec/models/merge_request_spec.rb | 8 +++++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 481a0f8d24..a3c3fb67b1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -28,6 +28,7 @@ v 8.5.0 (unreleased) - Support Akismet spam checking for creation of issues via API (Stan Hu) - Improve UI consistency between projects and groups lists - Add sort dropdown to dashboard projects page + - Hide remove source branch button when the MR is merged but new commits are pushed (Zeger-Jan van de Weg) v 8.4.3 - Increase lfs_objects size column to 8-byte integer to allow files larger diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 89b6c49b36..0036235250 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -284,7 +284,8 @@ class MergeRequest < ActiveRecord::Base def can_remove_source_branch?(current_user) !source_project.protected_branch?(source_branch) && !source_project.root_ref?(source_branch) && - Ability.abilities.allowed?(current_user, :push_code, source_project) + Ability.abilities.allowed?(current_user, :push_code, source_project) && + last_commit == source_project.commit(source_branch) end def mr_and_commit_notes diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 46f2f20b98..f9d0e1029d 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -226,9 +226,15 @@ describe MergeRequest, models: true do expect(subject.can_remove_source_branch?(user2)).to be_falsey end - it "is can be removed in all other cases" do + it "can be removed if the last commit is the head of the source branch" do + allow(subject.source_project).to receive(:commit).and_return(subject.last_commit) + expect(subject.can_remove_source_branch?(user)).to be_truthy end + + it "cannot be removed if the last commit is not also the head of the source branch" do + expect(subject.can_remove_source_branch?(user)).to be_falsey + end end describe "#reset_merge_when_build_succeeds" do From ff5f0894adbabc9a70cb93af9126d8fc19c13d0b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 4 Feb 2016 12:23:44 +0100 Subject: [PATCH 88/89] Sort projects by last activity for new issue dropdown When creating new issue from dashboard page I want to see projects sorted by last activity instead of ID Signed-off-by: Dmitriy Zaporozhets --- app/views/shared/_new_project_item_select.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml index 4609591282..1c58345278 100644 --- a/app/views/shared/_new_project_item_select.html.haml +++ b/app/views/shared/_new_project_item_select.html.haml @@ -1,6 +1,6 @@ - if @projects.any? .prepend-left-10.project-item-select-holder - = project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups] } + = project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at' } %a.btn.btn-new.new-project-item-select-button = icon('plus') = local_assigns[:label] From 70e44d63f7f1af81ddb0527e3a084c6ab692ea58 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 4 Feb 2016 12:38:25 +0100 Subject: [PATCH 89/89] In search autocomplete show only groups and projects you are member of For big instances search autocomplet is flooded with groups you have no access to and insternal/public projects you don't care. It affects way how easily you can go to group/project you are actually member of Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + app/helpers/search_helper.rb | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index fc123b22b1..3f457b3fea 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -28,6 +28,7 @@ v 8.5.0 (unreleased) - Support Akismet spam checking for creation of issues via API (Stan Hu) - Improve UI consistency between projects and groups lists - Add sort dropdown to dashboard projects page + - In seach autocomplete show only groups and projects you are member of v 8.4.3 - Increase lfs_objects size column to 8-byte integer to allow files larger diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index d4f7825862..1eb790b179 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -70,7 +70,7 @@ module SearchHelper # Autocomplete results for the current user's groups def groups_autocomplete(term, limit = 5) - Group.search(term).limit(limit).map do |group| + current_user.authorized_groups.search(term).limit(limit).map do |group| { label: "group: #{search_result_sanitize(group.name)}", url: group_path(group) @@ -80,7 +80,7 @@ module SearchHelper # Autocomplete results for the current user's projects def projects_autocomplete(term, limit = 5) - ProjectsFinder.new.execute(current_user).search_by_title(term). + current_user.authorized_projects.search_by_title(term). sorted_by_stars.non_archived.limit(limit).map do |p| { label: "project: #{search_result_sanitize(p.name_with_namespace)}",