From e451e7a16db4da4e2b01ebe64b0b9afc541a3829 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 11 Oct 2017 13:11:29 +0000 Subject: [PATCH 001/149] Merge branch 'rs-mysql-groups-dashboard-failure' into 'master' Fix a feature spec failing only on MySQL Closes #39003 See merge request gitlab-org/gitlab-ce!14811 --- spec/features/dashboard/groups_list_spec.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/spec/features/dashboard/groups_list_spec.rb b/spec/features/dashboard/groups_list_spec.rb index 533df7a325c..a6329b5c78d 100644 --- a/spec/features/dashboard/groups_list_spec.rb +++ b/spec/features/dashboard/groups_list_spec.rb @@ -1,14 +1,15 @@ require 'spec_helper' feature 'Dashboard Groups page', :js do - let!(:user) { create :user } - let!(:group) { create(:group) } - let!(:nested_group) { create(:group, :nested) } - let!(:another_group) { create(:group) } + let(:user) { create :user } + let(:group) { create(:group) } + let(:nested_group) { create(:group, :nested) } + let(:another_group) { create(:group) } it 'shows groups user is member of' do group.add_owner(user) nested_group.add_owner(user) + expect(another_group).to be_persisted sign_in(user) visit dashboard_groups_path @@ -22,6 +23,7 @@ feature 'Dashboard Groups page', :js do before do group.add_owner(user) nested_group.add_owner(user) + expect(another_group).to be_persisted sign_in(user) @@ -51,7 +53,7 @@ feature 'Dashboard Groups page', :js do end end - describe 'group with subgroups' do + describe 'group with subgroups', :nested_groups do let!(:subgroup) { create(:group, :public, parent: group) } before do @@ -90,7 +92,8 @@ feature 'Dashboard Groups page', :js do end describe 'when using pagination' do - let(:group2) { create(:group) } + let(:group) { create(:group, created_at: 5.days.ago) } + let(:group2) { create(:group, created_at: 2.days.ago) } before do group.add_owner(user) @@ -102,12 +105,9 @@ feature 'Dashboard Groups page', :js do visit dashboard_groups_path end - it 'shows pagination' do - expect(page).to have_selector('.gl-pagination') + it 'loads results for next page' do expect(page).to have_selector('.gl-pagination .page', count: 2) - end - it 'loads results for next page' do # Check first page expect(page).to have_content(group2.full_name) expect(page).to have_selector("#group-#{group2.id}") -- GitLab From 5f2901bf5b56caa3adfa3f63c87a68db4d2dd184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Trzci=C5=84ski?= Date: Wed, 11 Oct 2017 09:55:47 +0000 Subject: [PATCH 002/149] Merge branch 'fix/sm/move-callback-route-google_api-auth-callback-for-oauth-under' into 'master' Move callback route(`google_api/auth/callback`) for Oauth under `-` Closes #38911 See merge request gitlab-org/gitlab-ce!14802 --- config/routes/google_api.rb | 8 +++++--- lib/gitlab/path_regex.rb | 1 - 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/config/routes/google_api.rb b/config/routes/google_api.rb index 3fb236d3d51..a119b47c176 100644 --- a/config/routes/google_api.rb +++ b/config/routes/google_api.rb @@ -1,5 +1,7 @@ -namespace :google_api do - resource :auth, only: [], controller: :authorizations do - match :callback, via: [:get, :post] +scope '-' do + namespace :google_api do + resource :auth, only: [], controller: :authorizations do + match :callback, via: [:get, :post] + end end end diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb index e68160c8faf..7c02c9c5c48 100644 --- a/lib/gitlab/path_regex.rb +++ b/lib/gitlab/path_regex.rb @@ -33,7 +33,6 @@ module Gitlab explore favicon.ico files - google_api groups health_check help -- GitLab From 577539ea86376c49e330774cdeaea75d1803d378 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 10 Oct 2017 15:36:33 +0000 Subject: [PATCH 003/149] Merge branch 'fix-resolved-discussion' into 'master' Fix unable to expand text diff discussion comments Closes #38940 See merge request gitlab-org/gitlab-ce!14792 --- app/views/discussions/_diff_discussion.html.haml | 2 +- app/views/discussions/_diff_with_notes.html.haml | 2 +- app/views/discussions/_notes.html.haml | 4 ++-- spec/features/merge_requests/diffs_spec.rb | 8 ++------ 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/app/views/discussions/_diff_discussion.html.haml b/app/views/discussions/_diff_discussion.html.haml index 52279d0a870..4b6c4581eb3 100644 --- a/app/views/discussions/_diff_discussion.html.haml +++ b/app/views/discussions/_diff_discussion.html.haml @@ -7,4 +7,4 @@ %td.notes_line{ colspan: 2 } %td.notes_content .content{ class: ('hide' unless expanded) } - = render partial: "discussions/notes", collection: discussions, as: :discussion + = render partial: "discussions/notes", collection: discussions, as: :discussion, locals: { disable_collapse_class: true } diff --git a/app/views/discussions/_diff_with_notes.html.haml b/app/views/discussions/_diff_with_notes.html.haml index 636d06cab53..f9bfc01f213 100644 --- a/app/views/discussions/_diff_with_notes.html.haml +++ b/app/views/discussions/_diff_with_notes.html.haml @@ -24,4 +24,4 @@ = render partial: "projects/diffs/#{partial}", locals: { diff_file: diff_file, position: discussion.position.to_json, click_to_comment: false } .note-container - = render partial: "discussions/notes", locals: { discussion: discussion, show_toggle: false, show_image_comment_badge: true, disable_collapse: true } + = render partial: "discussions/notes", locals: { discussion: discussion, show_toggle: false, show_image_comment_badge: true, disable_collapse_class: true } diff --git a/app/views/discussions/_notes.html.haml b/app/views/discussions/_notes.html.haml index 9efcfef690f..1cc227428e9 100644 --- a/app/views/discussions/_notes.html.haml +++ b/app/views/discussions/_notes.html.haml @@ -1,5 +1,5 @@ -- disable_collapse = local_assigns.fetch(:disable_collapse, false) -- collapsed_class = 'collapsed' if discussion.resolved? && !disable_collapse +- disable_collapse_class = local_assigns.fetch(:disable_collapse_class, false) +- collapsed_class = 'collapsed' if discussion.resolved? && !disable_collapse_class - badge_counter = discussion_counter + 1 if local_assigns[:discussion_counter] - show_toggle = local_assigns.fetch(:show_toggle, true) - show_image_comment_badge = local_assigns.fetch(:show_image_comment_badge, false) diff --git a/spec/features/merge_requests/diffs_spec.rb b/spec/features/merge_requests/diffs_spec.rb index 80fb7335989..2adca58620f 100644 --- a/spec/features/merge_requests/diffs_spec.rb +++ b/spec/features/merge_requests/diffs_spec.rb @@ -44,12 +44,8 @@ feature 'Diffs URL', :js do visit "#{diffs_project_merge_request_path(project, merge_request)}#{fragment}" end - it 'shows collapsed note' do - wait_for_requests - - expect(page).to have_selector('.discussion-notes.collapsed') do |note_container| - expect(note_container).to have_selector(fragment, visible: false) - end + it 'shows expanded note' do + expect(page).to have_selector(fragment, visible: true) end end end -- GitLab From 37d0178bd0e4d603b1ffc824f545b86e21680575 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Tue, 10 Oct 2017 18:23:39 +0000 Subject: [PATCH 004/149] Merge branch 'fix-dropdown' into 'master' Remove not selector increasing specificity of rules Closes #38958 See merge request gitlab-org/gitlab-ce!14789 --- app/assets/stylesheets/framework/dropdowns.scss | 2 +- app/assets/stylesheets/framework/header.scss | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 5b950ae0ba0..9dcf332eee2 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -749,7 +749,7 @@ margin-bottom: $dropdown-vertical-offset; } - li:not(.dropdown-bold-header) { + li { display: block; padding: 0 1px; diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 22945e935ef..d79444fad79 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -161,9 +161,10 @@ } } - .dropdown-bold-header { + li.dropdown-bold-header { color: $gl-text-color-secondary; font-size: 12px; + padding: 0 16px; } .navbar-collapse { -- GitLab From d8103dd4a498530a9d4ceba62d909111d2cd3a40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 12 Oct 2017 13:51:47 +0000 Subject: [PATCH 005/149] Merge branch 'update-templates' into 'master' Update templates See merge request gitlab-org/gitlab-ce!14844 --- vendor/gitignore/Android.gitignore | 3 ++- vendor/gitignore/Autotools.gitignore | 9 +++++++ vendor/gitignore/Elixir.gitignore | 2 ++ vendor/gitignore/ExtJs.gitignore | 2 ++ vendor/gitignore/Global/Matlab.gitignore | 2 +- vendor/gitignore/Global/Xcode.gitignore | 18 ++++++------- vendor/gitignore/Global/macOS.gitignore | 2 +- vendor/gitignore/Joomla.gitignore | 2 +- vendor/gitignore/OCaml.gitignore | 3 +++ vendor/gitignore/Python.gitignore | 5 ++++ vendor/gitignore/Qt.gitignore | 2 -- vendor/gitignore/TeX.gitignore | 1 + vendor/gitignore/Terraform.gitignore | 3 +++ vendor/gitignore/Umbraco.gitignore | 4 +++ vendor/gitignore/VisualStudio.gitignore | 6 +++++ vendor/gitignore/ZendFramework.gitignore | 1 - vendor/gitlab-ci-yml/Go.gitlab-ci.yml | 2 +- vendor/gitlab-ci-yml/Maven.gitlab-ci.yml | 7 +++-- vendor/gitlab-ci-yml/Python.gitlab-ci.yml | 32 +++++++++++++++++++++++ 19 files changed, 85 insertions(+), 21 deletions(-) create mode 100644 vendor/gitlab-ci-yml/Python.gitlab-ci.yml diff --git a/vendor/gitignore/Android.gitignore b/vendor/gitignore/Android.gitignore index 520a86352f7..c79ba5080a3 100644 --- a/vendor/gitignore/Android.gitignore +++ b/vendor/gitignore/Android.gitignore @@ -41,7 +41,8 @@ captures/ .idea/libraries # Keystore files -*.jks +# Uncomment the following line if you do not want to check your keystore files in. +#*.jks # External native build folder generated in Android Studio 2.2 and later .externalNativeBuild diff --git a/vendor/gitignore/Autotools.gitignore b/vendor/gitignore/Autotools.gitignore index e3923f96fce..ffa6ecc3f9b 100644 --- a/vendor/gitignore/Autotools.gitignore +++ b/vendor/gitignore/Autotools.gitignore @@ -31,3 +31,12 @@ Makefile.in # http://www.gnu.org/software/texinfo /texinfo.tex + +# http://www.gnu.org/software/m4/ + +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 +autom4te.cache diff --git a/vendor/gitignore/Elixir.gitignore b/vendor/gitignore/Elixir.gitignore index ac67aaf3243..b6d65867dac 100644 --- a/vendor/gitignore/Elixir.gitignore +++ b/vendor/gitignore/Elixir.gitignore @@ -1,6 +1,8 @@ /_build /cover /deps +/doc +/.fetch erl_crash.dump *.ez *.beam diff --git a/vendor/gitignore/ExtJs.gitignore b/vendor/gitignore/ExtJs.gitignore index c92aea0fe0c..ab97a8cc3e1 100644 --- a/vendor/gitignore/ExtJs.gitignore +++ b/vendor/gitignore/ExtJs.gitignore @@ -10,3 +10,5 @@ ext/ modern.json modern.jsonp resources/sass/.sass-cache/ +resources/.arch-internal-preview.css +.arch-internal-preview.css diff --git a/vendor/gitignore/Global/Matlab.gitignore b/vendor/gitignore/Global/Matlab.gitignore index 09dfde64b5f..cca150a88dd 100644 --- a/vendor/gitignore/Global/Matlab.gitignore +++ b/vendor/gitignore/Global/Matlab.gitignore @@ -19,4 +19,4 @@ slprj/ octave-workspace # Simulink autosave extension -.autosave +*.autosave diff --git a/vendor/gitignore/Global/Xcode.gitignore b/vendor/gitignore/Global/Xcode.gitignore index 37de8bb4793..cd0c7d3e45a 100644 --- a/vendor/gitignore/Global/Xcode.gitignore +++ b/vendor/gitignore/Global/Xcode.gitignore @@ -2,11 +2,17 @@ # # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore -## Build generated +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) build/ DerivedData/ - -## Various settings +*.moved-aside *.pbxuser !default.pbxuser *.mode1v3 @@ -15,9 +21,3 @@ DerivedData/ !default.mode2v3 *.perspectivev3 !default.perspectivev3 -xcuserdata/ - -## Other -*.moved-aside -*.xccheckout -*.xcscmblueprint diff --git a/vendor/gitignore/Global/macOS.gitignore b/vendor/gitignore/Global/macOS.gitignore index 9d1061e8bc4..135767fc075 100644 --- a/vendor/gitignore/Global/macOS.gitignore +++ b/vendor/gitignore/Global/macOS.gitignore @@ -1,5 +1,5 @@ # General -*.DS_Store +.DS_Store .AppleDouble .LSOverride diff --git a/vendor/gitignore/Joomla.gitignore b/vendor/gitignore/Joomla.gitignore index 53a74e74657..b6bf3a9c96a 100644 --- a/vendor/gitignore/Joomla.gitignore +++ b/vendor/gitignore/Joomla.gitignore @@ -251,7 +251,7 @@ /administrator/language/en-GB/en-GB.tpl_hathor.sys.ini /administrator/language/en-GB/en-GB.xml /administrator/language/overrides/* -/administrator/logs/index.html +/administrator/logs/* /administrator/manifests/* /administrator/modules/mod_custom/* /administrator/modules/mod_feed/* diff --git a/vendor/gitignore/OCaml.gitignore b/vendor/gitignore/OCaml.gitignore index f7817ae5c36..da0b20424a0 100644 --- a/vendor/gitignore/OCaml.gitignore +++ b/vendor/gitignore/OCaml.gitignore @@ -18,3 +18,6 @@ _build/ # oasis generated files setup.data setup.log + +# Merlin configuring file for Vim and Emacs +.merlin diff --git a/vendor/gitignore/Python.gitignore b/vendor/gitignore/Python.gitignore index 113294a5f18..af2f537516d 100644 --- a/vendor/gitignore/Python.gitignore +++ b/vendor/gitignore/Python.gitignore @@ -23,6 +23,7 @@ wheels/ *.egg-info/ .installed.cfg *.egg +MANIFEST # PyInstaller # Usually these files are written by a python script from a template @@ -51,6 +52,8 @@ coverage.xml # Django stuff: *.log +.static_storage/ +.media/ local_settings.py # Flask stuff: @@ -84,6 +87,8 @@ celerybeat-schedule env/ venv/ ENV/ +env.bak/ +venv.bak/ # Spyder project settings .spyderproject diff --git a/vendor/gitignore/Qt.gitignore b/vendor/gitignore/Qt.gitignore index fe67fdf1ee6..037a1e75790 100644 --- a/vendor/gitignore/Qt.gitignore +++ b/vendor/gitignore/Qt.gitignore @@ -31,11 +31,9 @@ ui_*.h Makefile* *build-* - # Qt unit tests target_wrapper.* - # QtCreator *.autosave diff --git a/vendor/gitignore/TeX.gitignore b/vendor/gitignore/TeX.gitignore index a0322dbd35a..b6418e51766 100644 --- a/vendor/gitignore/TeX.gitignore +++ b/vendor/gitignore/TeX.gitignore @@ -13,6 +13,7 @@ ## Intermediate documents: *.dvi +*.xdv *-converted-to.* # these rules might exclude image files for figures etc. # *.ps diff --git a/vendor/gitignore/Terraform.gitignore b/vendor/gitignore/Terraform.gitignore index f20453be963..9b5aebb1b35 100644 --- a/vendor/gitignore/Terraform.gitignore +++ b/vendor/gitignore/Terraform.gitignore @@ -5,3 +5,6 @@ # Module directory .terraform/ + +# Variable values for development +terraform.tfvars diff --git a/vendor/gitignore/Umbraco.gitignore b/vendor/gitignore/Umbraco.gitignore index ea05e1fb2a9..b6b0743f62a 100644 --- a/vendor/gitignore/Umbraco.gitignore +++ b/vendor/gitignore/Umbraco.gitignore @@ -1,3 +1,7 @@ +## Ignore Umbraco files/folders generated for each instance +## +## Get latest from https://github.com/github/gitignore/blob/master/Umbraco.gitignore + # Note: VisualStudio gitignore rules may also be relevant # Umbraco diff --git a/vendor/gitignore/VisualStudio.gitignore b/vendor/gitignore/VisualStudio.gitignore index f652b45c2ee..0867ec5a7ee 100644 --- a/vendor/gitignore/VisualStudio.gitignore +++ b/vendor/gitignore/VisualStudio.gitignore @@ -96,6 +96,9 @@ ipch/ *.vspx *.sap +# Visual Studio Trace Files +*.e2e + # TFS 2012 Local Workspace $tf/ @@ -297,3 +300,6 @@ __pycache__/ *.btm.cs *.odx.cs *.xsd.cs + +# OpenCover UI analysis results +OpenCover/ diff --git a/vendor/gitignore/ZendFramework.gitignore b/vendor/gitignore/ZendFramework.gitignore index 80adb154900..f0b7d8585b7 100644 --- a/vendor/gitignore/ZendFramework.gitignore +++ b/vendor/gitignore/ZendFramework.gitignore @@ -19,7 +19,6 @@ temp/ data/DoctrineORMModule/Proxy/ data/DoctrineORMModule/cache/ - # Legacy ZF1 demos/ extras/documentation diff --git a/vendor/gitlab-ci-yml/Go.gitlab-ci.yml b/vendor/gitlab-ci-yml/Go.gitlab-ci.yml index 8a214352d2a..86e4985d8d2 100644 --- a/vendor/gitlab-ci-yml/Go.gitlab-ci.yml +++ b/vendor/gitlab-ci-yml/Go.gitlab-ci.yml @@ -29,7 +29,7 @@ format: compile: stage: build script: - - go build -race -ldflags "-extldflags '-static'" -o mybinary + - go build -race -ldflags "-extldflags '-static'" -o $CI_PROJECT_DIR/mybinary artifacts: paths: - mybinary diff --git a/vendor/gitlab-ci-yml/Maven.gitlab-ci.yml b/vendor/gitlab-ci-yml/Maven.gitlab-ci.yml index 91b096654d1..ba2efbd03a0 100644 --- a/vendor/gitlab-ci-yml/Maven.gitlab-ci.yml +++ b/vendor/gitlab-ci-yml/Maven.gitlab-ci.yml @@ -7,8 +7,8 @@ # This template will build and test your projects as well as create the documentation. # # * Caches downloaded dependencies and plugins between invocation. -# * Does only verify merge requests but deploy built artifacts of the -# master branch. +# * Verify but don't deploy merge requests. +# * Deploy built artifacts from master branch only. # * Shows how to use multiple jobs in test stage for verifying functionality # with multiple JDKs. # * Uses site:stage to collect the documentation for multi-module projects. @@ -20,7 +20,7 @@ variables: MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true" # As of Maven 3.3.0 instead of this you may define these options in `.mvn/maven.config` so the same config is used # when running from the command line. - # `installAtEnd` and `deployAtEnd`are only effective with recent version of the corresponding plugins. + # `installAtEnd` and `deployAtEnd` are only effective with recent version of the corresponding plugins. MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true" # Cache downloaded dependencies and plugins between builds. @@ -100,4 +100,3 @@ pages: - public only: - master - diff --git a/vendor/gitlab-ci-yml/Python.gitlab-ci.yml b/vendor/gitlab-ci-yml/Python.gitlab-ci.yml new file mode 100644 index 00000000000..a2882a5407d --- /dev/null +++ b/vendor/gitlab-ci-yml/Python.gitlab-ci.yml @@ -0,0 +1,32 @@ +# This file is a template, and might need editing before it works on your project. +image: python:latest + +before_script: + - python -V # Print out python version for debugging + +test: + script: + - python setup.py test + - pip install tox flake8 # you can also use tox + - tox -e py36,flake8 + +run: + script: + - python setup.py bdist_wheel + # an alternative approach is to install and run: + - pip install dist/* + # run the command here + artifacts: + paths: + - dist/*.whl + +pages: + script: + - pip install sphinx sphinx-rtd-theme + - cd doc ; make html + - mv build/html/ ../public/ + artifacts: + paths: + - public + only: + - master -- GitLab From 39898bdf9b1b9c19888ee15377886372f8a2db6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 12 Oct 2017 14:54:34 +0000 Subject: [PATCH 006/149] Merge branch 'update-installation-doc-for-10-1' into 'master' Update installation doc for 10.1 See merge request gitlab-org/gitlab-ce!14843 --- doc/install/installation.md | 6 +++--- doc/update/10.0-to-10.1.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index af6c797dc00..2c93297ca2f 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -121,7 +121,7 @@ The use of Ruby version managers such as [RVM], [rbenv] or [chruby] with GitLab in production, frequently leads to hard to diagnose problems. For example, GitLab Shell is called from OpenSSH, and having a version manager can prevent pushing and pulling over SSH. Version managers are not supported and we strongly -advise everyone to follow the instructions below to use a system Ruby. +advise everyone to follow the instructions below to use a system Ruby. Linux distributions generally have older versions of Ruby available, so these instructions are designed to install Ruby from the official source code. @@ -299,9 +299,9 @@ sudo usermod -aG redis git ### Clone the Source # Clone GitLab repository - sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 10-0-stable gitlab + sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 10-1-stable gitlab -**Note:** You can change `10-0-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! +**Note:** You can change `10-1-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! ### Configure It diff --git a/doc/update/10.0-to-10.1.md b/doc/update/10.0-to-10.1.md index 4a9384f3ad6..dc14c779026 100644 --- a/doc/update/10.0-to-10.1.md +++ b/doc/update/10.0-to-10.1.md @@ -150,7 +150,7 @@ sudo -u git -H make #### New Gitaly configuration options required -In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell'. +In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`. ```shell echo ' @@ -335,11 +335,11 @@ sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production If all items are green, then congratulations, the upgrade is complete! -## Things went south? Revert to previous version (9.5) +## Things went south? Revert to previous version (10.0) ### 1. Revert the code to the previous version -Follow the [upgrade guide from 9.4 to 9.5](9.4-to-9.5.md), except for the +Follow the [upgrade guide from 9.5 to 10.0](9.5-to-10.0.md), except for the database migration (the backup is already migrated to the previous version). ### 2. Restore from the backup -- GitLab From 47e7e9c32412547667c33c35c775d73edf2a1b64 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Thu, 12 Oct 2017 09:38:57 +0000 Subject: [PATCH 007/149] Merge branch 'docs/gke-cluster' into 'master' Add docs for GKE integration See merge request gitlab-org/gitlab-ce!14712 --- doc/integration/google.md | 138 +++++++++++++++++------------ doc/user/permissions.md | 1 + doc/user/project/clusters/index.md | 90 +++++++++++++++++++ doc/user/project/index.md | 2 + 4 files changed, 172 insertions(+), 59 deletions(-) create mode 100644 doc/user/project/clusters/index.md diff --git a/doc/integration/google.md b/doc/integration/google.md index d5b523e6dc0..0611cbb59dc 100644 --- a/doc/integration/google.md +++ b/doc/integration/google.md @@ -1,83 +1,92 @@ # Google OAuth2 OmniAuth Provider -To enable the Google OAuth2 OmniAuth provider you must register your application with Google. Google will generate a client ID and secret key for you to use. - -1. Sign in to the [Google Developers Console](https://console.developers.google.com/) with the Google account you want to use to register GitLab. - -1. Select "Create Project". - -1. Provide the project information - - Project name: 'GitLab' works just fine here. - - Project ID: Must be unique to all Google Developer registered applications. Google provides a randomly generated Project ID by default. You can use the randomly generated ID or choose a new one. -1. Refresh the page. You should now see your new project in the list. Click on the project. - -1. Select the "Google APIs" tab in the Overview. - -1. Select and enable the following Google APIs - listed under "Popular APIs" - - Enable `Contacts API` - - Enable `Google+ API` +To enable the Google OAuth2 OmniAuth provider you must register your application +with Google. Google will generate a client ID and secret key for you to use. + +## Enabling Google OAuth + +In Google's side: + +1. Navigate to the [cloud resource manager](https://console.cloud.google.com/cloud-resource-manager) page +1. Select **Create Project** +1. Provide the project information: + - **Project name** - "GitLab" works just fine here. + - **Project ID** - Must be unique to all Google Developer registered applications. + Google provides a randomly generated Project ID by default. You can use + the randomly generated ID or choose a new one. +1. Refresh the page and you should see your new project in the list +1. Go to the [Google API Console](https://console.developers.google.com/apis/dashboard) +1. Select the previously created project form the upper left corner +1. Select **Credentials** from the sidebar +1. Select **OAuth consent screen** and fill the form with the required information +1. In the **Credentials** tab, select **Create credentials > OAuth client ID** +1. Fill in the required information + - **Application type** - Choose "Web Application" + - **Name** - Use the default one or provide your own + - **Authorized JavaScript origins** -This isn't really used by GitLab but go + ahead and put `https://gitlab.example.com` + - **Authorized redirect URIs** - Enter your domain name followed by the + callback URIs one at a time: -1. Select "Credentials" in the submenu. + ``` + https://gitlab.example.com/users/auth/google_oauth2/callback + https://gitlab.exampl.com/-/google_api/auth/callback + ``` -1. Select "Create New Client ID". +1. You should now be able to see a Client ID and Client secret. Note them down + or keep this page open as you will need them later. +1. From the **Dashboard** select **ENABLE APIS AND SERVICES > Google Cloud APIs > Container Engine API > Enable** -1. Fill in the required information - - Application type: "Web Application" - - Authorized JavaScript origins: This isn't really used by GitLab but go ahead and put 'https://gitlab.example.com' here. - - Authorized redirect URI: 'https://gitlab.example.com/users/auth/google_oauth2/callback' -1. Under the heading "Client ID for web application" you should see a Client ID and Client secret (see screenshot). Keep this page open as you continue configuration. ![Google app](img/google_app.png) +On your GitLab server: -1. On your GitLab server, open the configuration file. +1. Open the configuration file. - For omnibus package: + For Omnibus GitLab: ```sh - sudo editor /etc/gitlab/gitlab.rb + sudo editor /etc/gitlab/gitlab.rb ``` For installations from source: ```sh - cd /home/git/gitlab - - sudo -u git -H editor config/gitlab.yml + cd /home/git/gitlab + sudo -u git -H editor config/gitlab.yml ``` -1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings. - -1. Add the provider configuration: +1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings. +1. Add the provider configuration: - For omnibus package: + For Omnibus GitLab: ```ruby - gitlab_rails['omniauth_providers'] = [ - { - "name" => "google_oauth2", - "app_id" => "YOUR_APP_ID", - "app_secret" => "YOUR_APP_SECRET", - "args" => { "access_type" => "offline", "approval_prompt" => '' } - } - ] + gitlab_rails['omniauth_providers'] = [ + { + "name" => "google_oauth2", + "app_id" => "YOUR_APP_ID", + "app_secret" => "YOUR_APP_SECRET", + "args" => { "access_type" => "offline", "approval_prompt" => '' } + } + ] ``` For installations from source: ``` - - { name: 'google_oauth2', app_id: 'YOUR_APP_ID', - app_secret: 'YOUR_APP_SECRET', - args: { access_type: 'offline', approval_prompt: '' } } + - { name: 'google_oauth2', app_id: 'YOUR_APP_ID', + app_secret: 'YOUR_APP_SECRET', + args: { access_type: 'offline', approval_prompt: '' } } ``` -1. Change 'YOUR_APP_ID' to the client ID from the Google Developer page from step 10. - -1. Change 'YOUR_APP_SECRET' to the client secret from the Google Developer page from step 10. - -1. Make sure that you configure GitLab to use an FQDN as Google will not accept raw IP addresses. +1. Change `YOUR_APP_ID` to the client ID from the Google Developer page +1. Similarly, change `YOUR_APP_SECRET` to the client secret +1. Make sure that you configure GitLab to use an FQDN as Google will not accept + raw IP addresses. For Omnibus packages: ```ruby - external_url 'https://gitlab.example.com' + external_url 'https://gitlab.example.com' ``` For installations from source: @@ -88,21 +97,32 @@ To enable the Google OAuth2 OmniAuth provider you must register your application ``` 1. Save the configuration file. - 1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you installed GitLab via Omnibus or from source respectively. -On the sign in page there should now be a Google icon below the regular sign in form. Click the icon to begin the authentication process. Google will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in. +On the sign in page there should now be a Google icon below the regular sign in +form. Click the icon to begin the authentication process. Google will ask the +user to sign in and authorize the GitLab application. If everything goes well +the user will be returned to GitLab and will be signed in. ## Further Configuration -This further configuration is not required for Google authentication to function but it is strongly recommended. Taking these steps will increase usability for users by providing a little more recognition and branding. - -At this point, when users first try to authenticate to your GitLab installation with Google they will see a generic application name on the prompt screen. The prompt informs the user that "Project Default Service Account" would like to access their account. "Project Default Service Account" isn't very recognizable and may confuse or cause users to be concerned. This is easily changeable. - -1. Select 'Consent screen' in the left menu. (See steps 1, 4 and 5 above for instructions on how to get here if you closed your window). -1. Scroll down until you find "Product Name". Change the product name to something more descriptive. -1. Add any additional information as you wish - homepage, logo, privacy policy, etc. None of this is required, but it may help your users. +This further configuration is not required for Google authentication to function +but it is strongly recommended. Taking these steps will increase usability for +users by providing a little more recognition and branding. + +At this point, when users first try to authenticate to your GitLab installation +with Google they will see a generic application name on the prompt screen. The +prompt informs the user that "Project Default Service Account" would like to +access their account. "Project Default Service Account" isn't very recognizable +and may confuse or cause users to be concerned. This is easily changeable: + +1. Select 'Consent screen' in the left menu. (See steps 1, 4 and 5 above for + instructions on how to get here if you closed your window). +1. Scroll down until you find "Product Name". Change the product name to + something more descriptive. +1. Add any additional information as you wish - homepage, logo, privacy policy, + etc. None of this is required, but it may help your users. [reconfigure]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure [restart GitLab]: ../administration/restart_gitlab.md#installations-from-source diff --git a/doc/user/permissions.md b/doc/user/permissions.md index be72d42625a..6e1479ead2d 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -76,6 +76,7 @@ The following table depicts the various user permission levels in a project. | Force push to protected branches [^4] | | | | | | | Remove protected branches [^4] | | | | | | | Remove pages | | | | | ✓ | +| Manage clusters | | | | ✓ | ✓ | ## Project features permissions diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md new file mode 100644 index 00000000000..7d9e771f570 --- /dev/null +++ b/doc/user/project/clusters/index.md @@ -0,0 +1,90 @@ +# Connecting GitLab with GKE + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/35954) in 10.1. + +CAUTION: **Warning:** +The Cluster integration is currently in **Beta**. + +Connect your project to Google Container Engine (GKE) in a few steps. + +With a cluster associated to your project, you can use Review Apps, deploy your +applications, run your pipelines, and much more in an easy way. + +NOTE: **Note:** +The Cluster integration will eventually supersede the +[Kubernetes integration](../integrations/kubernetes.md). For the moment, +you can create only one cluster. + +## Prerequisites + +In order to be able to manage your GKE cluster through GitLab, the following +prerequisites must be met: + +- The [Google authentication integration](../../../integration/google.md) must + be enabled in GitLab at the instance level. If that's not the case, ask your + administrator to enable it. +- Your associated Google account must have the right privileges to manage + clusters on GKE. That would mean that a + [billing account](https://cloud.google.com/billing/docs/how-to/manage-billing-account) + must be set up. +- You must have Master [permissions] in order to be able to access the **Cluster** + page. + +If all of the above requirements are met, you can proceed to add a new cluster. + +## Adding a cluster + +NOTE: **Note:** +You need Master [permissions] and above to add a cluster. + +To add a new cluster: + +1. Navigate to your project's **CI/CD > Cluster** page. +1. Connect your Google account if you haven't done already by clicking the + "Sign-in with Google" button. +1. Fill in the requested values: + - **Cluster name** (required) - The name you wish to give the cluster. + - **GCP project ID** (required) - The ID of the project you created in your GCP + console that will host the Kubernetes cluster. This must **not** be confused + with the project name. Learn more about [Google Cloud Platform projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects). + - **Zone** - The zone under which the cluster will be created. Read more about + [the available zones](https://cloud.google.com/compute/docs/regions-zones/). + - **Number of nodes** - The number of nodes you wish the cluster to have. + - **Machine type** - The machine type of the Virtual Machine instance that + the cluster will be based on. Read more about [the available machine types](https://cloud.google.com/compute/docs/machine-types). + - **Project namespace** - The unique namespace for this project. By default you + don't have to fill it in; by leaving it blank, GitLab will create one for you. +1. Click the **Create cluster** button. + +After a few moments your cluster should be created. If something goes wrong, +you will be notified. + +Now, you can proceed to [enable the Cluster integration](#enabling-or-disabling-the-cluster-integration). + +## Enabling or disabling the Cluster integration + +After you have successfully added your cluster information, you can enable the +Cluster integration: + +1. Click the "Enabled/Disabled" switch +1. Hit **Save** for the changes to take effect + +You can now start using your Kubernetes cluster for your deployments. + +To disable the Cluster integration, follow the same procedure. + +## Removing the Cluster integration + +NOTE: **Note:** +You need Master [permissions] and above to remove a cluster integration. + +NOTE: **Note:** +When you remove a cluster, you only remove its relation to GitLab, not the +cluster itself. To remove the cluster, you can do so by visiting the GKE +dashboard or using `kubectl`. + +To remove the Cluster integration from your project, simply click on the +**Remove integration** button. You will then be able to follow the procedure +and [add a cluster](#adding-a-cluster) again. + +[permissions]: ../../permissions.md diff --git a/doc/user/project/index.md b/doc/user/project/index.md index 03bbc46bd8c..97d0d529886 100644 --- a/doc/user/project/index.md +++ b/doc/user/project/index.md @@ -63,6 +63,8 @@ common actions on issues or merge requests browse, and download job artifacts - [Pipeline settings](pipelines/settings.md): Set up Git strategy (choose the default way your repository is fetched from GitLab in a job), timeout (defines the maximum amount of time in minutes that a job is able run), custom path for `.gitlab-ci.yml`, test coverage parsing, pipeline's visibility, and much more + - [GKE cluster integration](clusters/index.md): Connecting your GitLab project + with Google Container Engine - [GitLab Pages](pages/index.md): Build, test, and deploy your static website with GitLab Pages -- GitLab From b50653ae19ed7b5e00d2ae78169ae4103a89e787 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Wed, 11 Oct 2017 10:46:05 +0000 Subject: [PATCH 008/149] Merge branch '35580-cannot-import-project-with-milestones' into 'master' fix the import :milestone from adding the group_id Closes #35580 See merge request gitlab-org/gitlab-ce!14657 --- ...-cannot-import-project-with-milestones.yml | 5 + .../import_export/project_tree_restorer.rb | 2 +- lib/gitlab/import_export/relation_factory.rb | 51 +++-- .../gitlab/import_export/project.group.json | 188 ++++++++++++++++++ .../gitlab/import_export/project.light.json | 51 ++--- .../project_tree_restorer_spec.rb | 134 ++++++++----- 6 files changed, 333 insertions(+), 98 deletions(-) create mode 100644 changelogs/unreleased/35580-cannot-import-project-with-milestones.yml create mode 100644 spec/lib/gitlab/import_export/project.group.json diff --git a/changelogs/unreleased/35580-cannot-import-project-with-milestones.yml b/changelogs/unreleased/35580-cannot-import-project-with-milestones.yml new file mode 100644 index 00000000000..b28105556db --- /dev/null +++ b/changelogs/unreleased/35580-cannot-import-project-with-milestones.yml @@ -0,0 +1,5 @@ +--- +title: Fix the project import with issues and milestones +merge_request: 14657 +author: +type: fixed diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 3bc095a99a9..639f4f0c3f0 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -2,7 +2,7 @@ module Gitlab module ImportExport class ProjectTreeRestorer # Relations which cannot have both group_id and project_id at the same time - RESTRICT_PROJECT_AND_GROUP = %i(milestones).freeze + RESTRICT_PROJECT_AND_GROUP = %i(milestone milestones).freeze def initialize(user:, shared:, project:) @path = File.join(shared.export_path, 'project.json') diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index a76cf1addc0..469b230377d 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -37,7 +37,7 @@ module Gitlab def initialize(relation_sym:, relation_hash:, members_mapper:, user:, project:) @relation_name = OVERRIDES[relation_sym] || relation_sym - @relation_hash = relation_hash.except('noteable_id').merge('project_id' => project.id) + @relation_hash = relation_hash.except('noteable_id') @members_mapper = members_mapper @user = user @project = project @@ -58,22 +58,21 @@ module Gitlab private def setup_models - if @relation_name == :notes - set_note_author - - # attachment is deprecated and note uploads are handled by Markdown uploader - @relation_hash['attachment'] = nil + case @relation_name + when :merge_request_diff then setup_st_diff_commits + when :merge_request_diff_files then setup_diff + when :notes then setup_note + when :project_label, :project_labels then setup_label + when :milestone, :milestones then setup_milestone + else + @relation_hash['project_id'] = @project.id end update_user_references update_project_references - handle_group_label if group_label? reset_tokens! remove_encrypted_attributes! - - set_st_diff_commits if @relation_name == :merge_request_diff - set_diff if @relation_name == :merge_request_diff_files end def update_user_references @@ -84,6 +83,12 @@ module Gitlab end end + def setup_note + set_note_author + # attachment is deprecated and note uploads are handled by Markdown uploader + @relation_hash['attachment'] = nil + end + # Sets the author for a note. If the user importing the project # has admin access, an actual mapping with new project members # will be used. Otherwise, a note stating the original author name @@ -136,11 +141,9 @@ module Gitlab @relation_hash['target_project_id'] && @relation_hash['target_project_id'] == @relation_hash['source_project_id'] end - def group_label? - @relation_hash['type'] == 'GroupLabel' - end + def setup_label + return unless @relation_hash['type'] == 'GroupLabel' - def handle_group_label # If there's no group, move the label to a project label if @relation_hash['group_id'] @relation_hash['project_id'] = nil @@ -150,6 +153,14 @@ module Gitlab end end + def setup_milestone + if @relation_hash['group_id'] + @relation_hash['group_id'] = @project.group.id + else + @relation_hash['project_id'] = @project.id + end + end + def reset_tokens! return unless Gitlab::ImportExport.reset_tokens? && TOKEN_RESET_MODELS.include?(@relation_name.to_s) @@ -198,14 +209,14 @@ module Gitlab relation_class: relation_class) end - def set_st_diff_commits + def setup_st_diff_commits @relation_hash['st_diffs'] = @relation_hash.delete('utf8_st_diffs') HashUtil.deep_symbolize_array!(@relation_hash['st_diffs']) HashUtil.deep_symbolize_array_with_date!(@relation_hash['st_commits']) end - def set_diff + def setup_diff @relation_hash['diff'] = @relation_hash.delete('utf8_diff') end @@ -250,7 +261,13 @@ module Gitlab end def find_or_create_object! - finder_attributes = @relation_name == :group_label ? %w[title group_id] : %w[title project_id] + finder_attributes = if @relation_name == :group_label + %w[title group_id] + elsif parsed_relation_hash['project_id'] + %w[title project_id] + else + %w[title group_id] + end finder_hash = parsed_relation_hash.slice(*finder_attributes) if label? diff --git a/spec/lib/gitlab/import_export/project.group.json b/spec/lib/gitlab/import_export/project.group.json new file mode 100644 index 00000000000..82a1fbd2fc5 --- /dev/null +++ b/spec/lib/gitlab/import_export/project.group.json @@ -0,0 +1,188 @@ +{ + "description": "Nisi et repellendus ut enim quo accusamus vel magnam.", + "visibility_level": 10, + "archived": false, + "milestones": [ + { + "id": 1, + "title": "Project milestone", + "project_id": 8, + "description": "Project-level milestone", + "due_date": null, + "created_at": "2016-06-14T15:02:04.415Z", + "updated_at": "2016-06-14T15:02:04.415Z", + "state": "active", + "iid": 1, + "group_id": null + } + ], + "labels": [ + { + "id": 2, + "title": "project label", + "color": "#428bca", + "project_id": 8, + "created_at": "2016-07-22T08:55:44.161Z", + "updated_at": "2016-07-22T08:55:44.161Z", + "template": false, + "description": "", + "type": "ProjectLabel", + "priorities": [ + { + "id": 1, + "project_id": 5, + "label_id": 1, + "priority": 1, + "created_at": "2016-10-18T09:35:43.338Z", + "updated_at": "2016-10-18T09:35:43.338Z" + } + ] + } + ], + "issues": [ + { + "id": 1, + "title": "Fugiat est minima quae maxime non similique.", + "assignee_id": null, + "project_id": 8, + "author_id": 1, + "created_at": "2017-07-07T18:13:01.138Z", + "updated_at": "2017-08-15T18:37:40.807Z", + "branch_name": null, + "description": "Quam totam fuga numquam in eveniet.", + "state": "opened", + "iid": 1, + "updated_by_id": 1, + "confidential": false, + "deleted_at": null, + "due_date": null, + "moved_to_id": null, + "lock_version": null, + "time_estimate": 0, + "closed_at": null, + "last_edited_at": null, + "last_edited_by_id": null, + "group_milestone_id": null, + "milestone": { + "id": 1, + "title": "Project milestone", + "project_id": 8, + "description": "Project-level milestone", + "due_date": null, + "created_at": "2016-06-14T15:02:04.415Z", + "updated_at": "2016-06-14T15:02:04.415Z", + "state": "active", + "iid": 1, + "group_id": null + }, + "label_links": [ + { + "id": 11, + "label_id": 6, + "target_id": 1, + "target_type": "Issue", + "created_at": "2017-08-15T18:37:40.795Z", + "updated_at": "2017-08-15T18:37:40.795Z", + "label": { + "id": 6, + "title": "group label", + "color": "#A8D695", + "project_id": null, + "created_at": "2017-08-15T18:37:19.698Z", + "updated_at": "2017-08-15T18:37:19.698Z", + "template": false, + "description": "", + "group_id": 5, + "type": "GroupLabel", + "priorities": [] + } + }, + { + "id": 11, + "label_id": 2, + "target_id": 1, + "target_type": "Issue", + "created_at": "2017-08-15T18:37:40.795Z", + "updated_at": "2017-08-15T18:37:40.795Z", + "label": { + "id": 6, + "title": "project label", + "color": "#A8D695", + "project_id": null, + "created_at": "2017-08-15T18:37:19.698Z", + "updated_at": "2017-08-15T18:37:19.698Z", + "template": false, + "description": "", + "group_id": 5, + "type": "ProjectLabel", + "priorities": [] + } + } + ] + }, + { + "id": 2, + "title": "Fugiat est minima quae maxime non similique.", + "assignee_id": null, + "project_id": 8, + "author_id": 1, + "created_at": "2017-07-07T18:13:01.138Z", + "updated_at": "2017-08-15T18:37:40.807Z", + "branch_name": null, + "description": "Quam totam fuga numquam in eveniet.", + "state": "opened", + "iid": 2, + "updated_by_id": 1, + "confidential": false, + "deleted_at": null, + "due_date": null, + "moved_to_id": null, + "lock_version": null, + "time_estimate": 0, + "closed_at": null, + "last_edited_at": null, + "last_edited_by_id": null, + "group_milestone_id": null, + "milestone": { + "id": 2, + "title": "A group milestone", + "description": "Group-level milestone", + "due_date": null, + "created_at": "2016-06-14T15:02:04.415Z", + "updated_at": "2016-06-14T15:02:04.415Z", + "state": "active", + "iid": 1, + "group_id": 100 + }, + "label_links": [ + { + "id": 11, + "label_id": 2, + "target_id": 1, + "target_type": "Issue", + "created_at": "2017-08-15T18:37:40.795Z", + "updated_at": "2017-08-15T18:37:40.795Z", + "label": { + "id": 2, + "title": "project label", + "color": "#A8D695", + "project_id": null, + "created_at": "2017-08-15T18:37:19.698Z", + "updated_at": "2017-08-15T18:37:19.698Z", + "template": false, + "description": "", + "group_id": 5, + "type": "ProjectLabel", + "priorities": [] + } + } + ] + } + ], + "snippets": [ + + ], + "hooks": [ + + ] +} diff --git a/spec/lib/gitlab/import_export/project.light.json b/spec/lib/gitlab/import_export/project.light.json index 2d8f3d4a566..02450478a77 100644 --- a/spec/lib/gitlab/import_export/project.light.json +++ b/spec/lib/gitlab/import_export/project.light.json @@ -5,9 +5,9 @@ "milestones": [ { "id": 1, - "title": "test milestone", + "title": "Project milestone", "project_id": 8, - "description": "test milestone", + "description": "Project-level milestone", "due_date": null, "created_at": "2016-06-14T15:02:04.415Z", "updated_at": "2016-06-14T15:02:04.415Z", @@ -19,7 +19,7 @@ "labels": [ { "id": 2, - "title": "test2", + "title": "A project label", "color": "#428bca", "project_id": 8, "created_at": "2016-07-22T08:55:44.161Z", @@ -63,28 +63,19 @@ "last_edited_at": null, "last_edited_by_id": null, "group_milestone_id": null, + "milestone": { + "id": 1, + "title": "Project milestone", + "project_id": 8, + "description": "Project-level milestone", + "due_date": null, + "created_at": "2016-06-14T15:02:04.415Z", + "updated_at": "2016-06-14T15:02:04.415Z", + "state": "active", + "iid": 1, + "group_id": null + }, "label_links": [ - { - "id": 11, - "label_id": 6, - "target_id": 1, - "target_type": "Issue", - "created_at": "2017-08-15T18:37:40.795Z", - "updated_at": "2017-08-15T18:37:40.795Z", - "label": { - "id": 6, - "title": "group label", - "color": "#A8D695", - "project_id": null, - "created_at": "2017-08-15T18:37:19.698Z", - "updated_at": "2017-08-15T18:37:19.698Z", - "template": false, - "description": "", - "group_id": 5, - "type": "GroupLabel", - "priorities": [] - } - }, { "id": 11, "label_id": 2, @@ -94,14 +85,14 @@ "updated_at": "2017-08-15T18:37:40.795Z", "label": { "id": 6, - "title": "project label", + "title": "Another project label", "color": "#A8D695", "project_id": null, "created_at": "2017-08-15T18:37:19.698Z", "updated_at": "2017-08-15T18:37:19.698Z", "template": false, "description": "", - "group_id": 5, + "group_id": null, "type": "ProjectLabel", "priorities": [] } @@ -109,10 +100,6 @@ ] } ], - "snippets": [ - - ], - "hooks": [ - - ] + "snippets": [], + "hooks": [] } diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index efe11ca794a..4301eee17dc 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -24,7 +24,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do context 'JSON' do it 'restores models based on JSON' do - expect(@restored_project_json).to be true + expect(@restored_project_json).to be_truthy end it 'restore correct project features' do @@ -182,6 +182,53 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do end end + shared_examples 'restores project successfully' do + it 'correctly restores project' do + expect(shared.errors).to be_empty + expect(restored_project_json).to be_truthy + end + end + + shared_examples 'restores project correctly' do |**results| + it 'has labels' do + expect(project.labels.size).to eq(results.fetch(:labels, 0)) + end + + it 'has label priorities' do + expect(project.labels.first.priorities).not_to be_empty + end + + it 'has milestones' do + expect(project.milestones.size).to eq(results.fetch(:milestones, 0)) + end + + it 'has issues' do + expect(project.issues.size).to eq(results.fetch(:issues, 0)) + end + + it 'has issue with group label and project label' do + labels = project.issues.first.labels + + expect(labels.where(type: "ProjectLabel").count).to eq(results.fetch(:first_issue_labels, 0)) + end + end + + shared_examples 'restores group correctly' do |**results| + it 'has group label' do + expect(project.group.labels.size).to eq(results.fetch(:labels, 0)) + end + + it 'has group milestone' do + expect(project.group.milestones.size).to eq(results.fetch(:milestones, 0)) + end + + it 'has issue with group label' do + labels = project.issues.first.labels + + expect(labels.where(type: "GroupLabel").count).to eq(results.fetch(:first_issue_labels, 0)) + end + end + context 'Light JSON' do let(:user) { create(:user) } let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: "", project_path: 'path') } @@ -190,33 +237,45 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do let(:restored_project_json) { project_tree_restorer.restore } before do - project_tree_restorer.instance_variable_set(:@path, "spec/lib/gitlab/import_export/project.light.json") - allow(shared).to receive(:export_path).and_return('spec/lib/gitlab/import_export/') end - context 'project.json file access check' do - it 'does not read a symlink' do - Dir.mktmpdir do |tmpdir| - setup_symlink(tmpdir, 'project.json') - allow(shared).to receive(:export_path).and_call_original + context 'with a simple project' do + before do + project_tree_restorer.instance_variable_set(:@path, "spec/lib/gitlab/import_export/project.light.json") + + restored_project_json + end + + it_behaves_like 'restores project correctly', + issues: 1, + labels: 1, + milestones: 1, + first_issue_labels: 1 - restored_project_json + context 'project.json file access check' do + it 'does not read a symlink' do + Dir.mktmpdir do |tmpdir| + setup_symlink(tmpdir, 'project.json') + allow(shared).to receive(:export_path).and_call_original - expect(shared.errors.first).to be_nil + restored_project_json + + expect(shared.errors).to be_empty + end end end - end - context 'when there is an existing build with build token' do - it 'restores project json correctly' do - create(:ci_build, token: 'abcd') + context 'when there is an existing build with build token' do + before do + create(:ci_build, token: 'abcd') + end - expect(restored_project_json).to be true + it_behaves_like 'restores project successfully' end end - context 'with group' do + context 'with a project that has a group' do let!(:project) do create(:project, :builds_disabled, @@ -227,43 +286,22 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do end before do - project_tree_restorer.instance_variable_set(:@path, "spec/lib/gitlab/import_export/project.light.json") + project_tree_restorer.instance_variable_set(:@path, "spec/lib/gitlab/import_export/project.group.json") restored_project_json end - it 'correctly restores project' do - expect(restored_project_json).to be_truthy - expect(shared.errors).to be_empty - end + it_behaves_like 'restores project successfully' + it_behaves_like 'restores project correctly', + issues: 2, + labels: 1, + milestones: 1, + first_issue_labels: 1 - it 'has labels' do - expect(project.labels.count).to eq(2) - end - - it 'creates group label' do - expect(project.group.labels.count).to eq(1) - end - - it 'has label priorities' do - expect(project.labels.first.priorities).not_to be_empty - end - - it 'has milestones' do - expect(project.milestones.count).to eq(1) - end - - it 'has issue' do - expect(project.issues.count).to eq(1) - expect(project.issues.first.labels.count).to eq(2) - end - - it 'has issue with group label and project label' do - labels = project.issues.first.labels - - expect(labels.where(type: "GroupLabel").count).to eq(1) - expect(labels.where(type: "ProjectLabel").count).to eq(1) - end + it_behaves_like 'restores group correctly', + labels: 1, + milestones: 1, + first_issue_labels: 1 end end end -- GitLab From e1b641bb2b64811a14d71b2a3aa8b8500e023231 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 11 Oct 2017 09:07:20 +0000 Subject: [PATCH 009/149] Merge branch '37399-simplify-project-page' into 'master' Simplify project page Closes #37399 and #38839 See merge request gitlab-org/gitlab-ce!14669 --- .../javascripts/projects/project_new.js | 40 ++++++ app/assets/stylesheets/framework.scss | 1 + app/assets/stylesheets/framework/tabs.scss | 35 ++++++ .../stylesheets/framework/variables.scss | 8 -- app/assets/stylesheets/pages/members.scss | 29 ----- app/assets/stylesheets/pages/projects.scss | 115 ++++++++++++++---- .../projects/_new_project_fields.html.haml | 41 +++++++ .../projects/_project_templates.html.haml | 30 +++-- app/views/projects/new.html.haml | 94 +++++--------- .../projects/project_members/index.html.haml | 4 +- app/views/shared/icons/_express.svg | 7 +- app/views/shared/icons/_rails.svg | 7 +- app/views/shared/icons/_spring.svg | 7 +- lib/gitlab/project_template.rb | 12 +- .../import_export/import_file_spec.rb | 20 ++- spec/features/projects/new_project_spec.rb | 37 ++++-- spec/features/projects_spec.rb | 5 +- spec/lib/gitlab/project_template_spec.rb | 8 +- 18 files changed, 313 insertions(+), 187 deletions(-) create mode 100644 app/assets/stylesheets/framework/tabs.scss create mode 100644 app/views/projects/_new_project_fields.html.haml diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js index 7f972b6f6ee..3ecc0c2a6e5 100644 --- a/app/assets/javascripts/projects/project_new.js +++ b/app/assets/javascripts/projects/project_new.js @@ -29,6 +29,12 @@ const bindEvents = () => { const $newProjectForm = $('#new_project'); const $projectImportUrl = $('#project_import_url'); const $projectPath = $('#project_path'); + const $useTemplateBtn = $('.template-button > input'); + const $projectFieldsForm = $('.project-fields-form'); + const $selectedTemplateText = $('.selected-template'); + const $changeTemplateBtn = $('.change-template'); + const $selectedIcon = $('.selected-icon svg'); + const $templateProjectNameInput = $('#template-project-name #project_path'); if ($newProjectForm.length !== 1) { return; @@ -48,6 +54,40 @@ const bindEvents = () => { $('.btn_import_gitlab_project').attr('href', `${importHref}?namespace_id=${$('#project_namespace_id').val()}&path=${$projectPath.val()}`); }); + function chooseTemplate() { + $('.template-option').hide(); + $projectFieldsForm.addClass('selected'); + $selectedIcon.removeClass('active'); + const value = $(this).val(); + const templates = { + rails: { + text: 'Ruby on Rails', + icon: '.selected-icon .icon-rails', + }, + express: { + text: 'NodeJS Express', + icon: '.selected-icon .icon-node-express', + }, + spring: { + text: 'Spring', + icon: '.selected-icon .icon-java-spring', + }, + }; + + const selectedTemplate = templates[value]; + $selectedTemplateText.text(selectedTemplate.text); + $(selectedTemplate.icon).addClass('active'); + $templateProjectNameInput.focus(); + } + + $useTemplateBtn.on('change', chooseTemplate); + + $changeTemplateBtn.on('click', () => { + $('.template-option').show(); + $projectFieldsForm.removeClass('selected'); + $useTemplateBtn.prop('checked', false); + }); + $newProjectForm.on('submit', () => { $projectPath.val($projectPath.val().trim()); }); diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index c7be94e2c8e..0d7a5cba928 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -38,6 +38,7 @@ @import "framework/new-sidebar"; @import "framework/tables"; @import "framework/notes"; +@import "framework/tabs"; @import "framework/timeline"; @import "framework/tooltips"; @import "framework/typography"; diff --git a/app/assets/stylesheets/framework/tabs.scss b/app/assets/stylesheets/framework/tabs.scss new file mode 100644 index 00000000000..c8ba14b7066 --- /dev/null +++ b/app/assets/stylesheets/framework/tabs.scss @@ -0,0 +1,35 @@ +.gitlab-tabs { + background: $gray-light; + border: 1px solid $border-color; + + li { + width: 50%; + + &:not(:last-child) { + border-right: 1px solid $border-color; + } + + &.active { + background: $white-light; + } + + a { + width: 100%; + text-align: center; + } + } +} + +.gitlab-tab-content { + border: 1px solid $border-color; + border-top: 0; + margin-bottom: $gl-padding; + + .tab-pane { + padding: $gl-padding; + + &.no-padding { + padding: 0; + } + } +} diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index bbbd16322eb..089a67a7c98 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -699,14 +699,6 @@ $perf-bar-bucket-color: #ccc; $perf-bar-bucket-box-shadow-from: rgba($white-light, .2); $perf-bar-bucket-box-shadow-to: rgba($black, .25); - -/* -Project Templates Icons -*/ -$rails: #c00; -$node: #353535; -$java: #70ad51; - /* Issuable warning */ diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index b3bab082a35..692acf74a58 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -3,41 +3,12 @@ border-bottom: 1px solid $border-color; } -.project-member-tabs { - background: $gray-light; - border: 1px solid $border-color; - - li { - width: 50%; - - &.active { - background: $white-light; - } - - &:first-child { - border-right: 1px solid $border-color; - } - - a { - width: 100%; - text-align: center; - } - } -} - .users-project-form { .btn-create { margin-right: 10px; } } -.project-member-tab-content { - padding: $gl-padding; - border: 1px solid $border-color; - border-top: 0; - margin-bottom: $gl-padding; -} - .member { .list-item-name { @media (min-width: $screen-sm-min) { diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index a086c11324d..61dc9f13d50 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -48,7 +48,8 @@ border: 1px solid $border-color; } - + .select2 a { + + .select2 a, + + .btn-default { border-top-left-radius: 0; border-bottom-left-radius: 0; } @@ -549,10 +550,92 @@ a.deploy-project-label { } } -.project-template, +.project-template { + > .form-group { + margin-bottom: 0; + } + + .template-option { + padding: $gl-padding $gl-padding $gl-padding ($gl-padding * 4); + position: relative; + + &:not(:first-child) { + border-top: 1px solid $border-color; + } + } + + .template-title { + font-size: 16px; + } + + .template-description { + margin: 6px 0 12px; + } + + .template-button { + input { + position: absolute; + clip: rect(0, 0, 0, 0); + } + } + + svg { + position: absolute; + left: $gl-padding; + top: $gl-padding; + } + + .project-fields-form { + display: none; + + &.selected { + display: block; + padding: $gl-padding; + } + } + + .template-input-group { + position: relative; + + @media (min-width: $screen-sm-min) { + display: flex; + } + + .input-group-addon { + flex: 1; + text-align: left; + padding-left: ($gl-padding * 3); + background-color: $white-light; + } + + .selected-template { + line-height: 20px; + } + + .selected-icon { + svg { + display: none; + top: 7px; + height: 20px; + width: 20px; + + &.active { + display: block; + } + } + } + } +} + +.gitlab-tab-content { + .import-project-pane { + padding-bottom: 6px; + } +} + .project-import { .form-group { - margin-bottom: 5px; + margin-bottom: 0; } .import-buttons { @@ -567,10 +650,6 @@ a.deploy-project-label { margin-right: 10px; } - .blank-option { - min-width: 70px; - } - .btn-template-icon { height: 24px; width: inherit; @@ -592,18 +671,6 @@ a.deploy-project-label { } } - .icon-rails path { - fill: $rails; - } - - .icon-node-express path { - fill: $node; - } - - .icon-java-spring path { - fill: $java; - } - > div { margin-bottom: 10px; padding-left: 0; @@ -611,10 +678,6 @@ a.deploy-project-label { } } -.project-templates-buttons .btn:last-child { - margin-right: 0; -} - .create-project-options { display: flex; @@ -1053,6 +1116,12 @@ pre.light-well { min-width: 100px; } + &.form-group { + @media (min-width: $screen-sm-min) { + margin-bottom: 0; + } + } + .select2-choice { border-top-right-radius: 0; border-bottom-right-radius: 0; diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml new file mode 100644 index 00000000000..a78a8e5d628 --- /dev/null +++ b/app/views/projects/_new_project_fields.html.haml @@ -0,0 +1,41 @@ +- visibility_level = params.dig(:project, :visibility_level) || default_project_visibility + +.row{ id: project_name_id } + .form-group.project-path.col-sm-6 + = f.label :namespace_id, class: 'label-light' do + %span + Project path + .input-group + - if current_user.can_select_namespace? + .input-group-addon + = root_url + = f.select :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), {}, { class: 'select2 js-select-namespace', tabindex: 1} + + - else + .input-group-addon.static-namespace + #{user_url(current_user.username)}/ + = f.hidden_field :namespace_id, value: current_user.namespace_id + .form-group.project-path.col-sm-6 + = f.label :path, class: 'label-light' do + %span + Project name + = f.text_field :path, placeholder: "my-awesome-project", class: "form-control", tabindex: 2, autofocus: true, required: true +- if current_user.can_create_group? + .help-block + Want to house several dependent projects under the same namespace? + = link_to "Create a group", new_group_path + +.form-group + = f.label :description, class: 'label-light' do + Project description + %span (optional) + = f.text_area :description, placeholder: 'Description format', class: "form-control", rows: 3, maxlength: 250 + +.form-group.visibility-level-setting + = f.label :visibility_level, class: 'label-light' do + Visibility Level + = link_to icon('question-circle'), help_page_path("public_access/public_access"), aria: { label: 'Documentation for Visibility Level' } + = render 'shared/visibility_level', f: f, visibility_level: visibility_level.to_i, can_change_visibility_level: true, form_model: @project, with_label: false + += f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4 += link_to 'Cancel', dashboard_projects_path, class: 'btn btn-cancel' diff --git a/app/views/projects/_project_templates.html.haml b/app/views/projects/_project_templates.html.haml index 5638b7da1b0..d50175727be 100644 --- a/app/views/projects/_project_templates.html.haml +++ b/app/views/projects/_project_templates.html.haml @@ -1,10 +1,24 @@ -.project-templates-buttons.import-buttons{ data: { toggle: "buttons" } } - .btn.blank-option.active - %input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: "blank", checked: "true", value: "" } - = icon('file-o', class: 'btn-template-icon') - Blank +.project-templates-buttons.import-buttons - Gitlab::ProjectTemplate.all.each do |template| - .btn - %input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name } + .template-option = custom_icon(template.logo) - = template.title + .template-title= template.title + .template-description= template.description + %label.btn.btn-success.template-button.choose-template.append-right-10{ for: template.name } + %input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name } + %span Use template + %a.btn.btn-default{ href: template.preview, rel: 'noopener noreferrer', target: '_blank' } Preview + + .project-fields-form + .form-group + %label.label-light + Template + .input-group.template-input-group + .input-group-addon + .selected-icon + - Gitlab::ProjectTemplate.all.each do |template| + = custom_icon(template.logo) + .selected-template + %button.btn.btn-default.change-template{ type: "button" } Change template + + = render 'new_project_fields', f: f, project_name_id: "template-project-name" diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index cc41b908946..0934c47a8e2 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -14,24 +14,40 @@ .col-lg-3.profile-settings-sidebar %h4.prepend-top-0 New project - - if import_sources_enabled? - %p - A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), #{link_to 'among other things', help_page_path("user/project/index.md", anchor: "projects-features"), target: '_blank'}. - %p - All features are enabled when you create a project, but you can disable the ones you don’t need in the project settings. + %p + A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), #{link_to 'among other things', help_page_path("user/project/index.md", anchor: "projects-features"), target: '_blank'}. + %p + All features are enabled when you create a project, but you can disable the ones you don’t need in the project settings. .col-lg-9.js-toggle-container - = form_for @project, html: { class: 'new_project' } do |f| - .create-project-options - .first-column + %ul.nav-links.gitlab-tabs{ role: 'tablist' } + %li.active{ role: 'presentation' } + %a{ href: '#blank-project-pane', id: 'blank-project-tab', data: { toggle: 'tab' }, role: 'tab' } + %span.hidden-xs Blank project + %span.visible-xs Blank + %li{ role: 'presentation' } + %a{ href: '#create-from-template-pane', id: 'create-from-template-tab', data: { toggle: 'tab' }, role: 'tab' } + %span.hidden-xs Create from template + %span.visible-xs Template + %li{ role: 'presentation' } + %a{ href: '#import-project-pane', id: 'import-project-tab', data: { toggle: 'tab' }, role: 'tab' } + %span.hidden-xs Import project + %span.visible-xs Import + + .tab-content.gitlab-tab-content + .tab-pane.active{ id: 'blank-project-pane', role: 'tabpanel' } + = form_for @project, html: { class: 'new_project' } do |f| + = render 'new_project_fields', f: f, project_name_id: "blank-project-name" + + .tab-pane.no-padding{ id: 'create-from-template-pane', role: 'tabpanel' } + = form_for @project, html: { class: 'new_project' } do |f| .project-template .form-group - = f.label :template_project, class: 'label-light' do - Create from template - = link_to icon('question-circle'), help_page_path("gitlab-basics/create-project"), target: '_blank', aria: { label: "What’s included in a template?" }, title: "What’s included in a template?", class: 'has-tooltip', data: { placement: 'top'} %div = render 'project_templates', f: f - - if import_sources_enabled? - .second-column + + .tab-pane.import-project-pane{ id: 'import-project-pane', role: 'tabpanel' } + = form_for @project, html: { class: 'new_project' } do |f| + - if import_sources_enabled? .project-import .form-group.clearfix = f.label :visibility_level, class: 'label-light' do #the label here seems wrong @@ -74,54 +90,10 @@ .import_gitlab_project.has-tooltip{ data: { container: 'body' } } = link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit' do = icon('gitlab', text: 'GitLab export') - - .row - .col-lg-12 - .js-toggle-content.hide - %hr - = render "shared/import_form", f: f - %hr - - .row - .form-group.col-xs-12.col-sm-6 - = f.label :namespace_id, class: 'label-light' do - %span - Project path - .form-group - .input-group - - if current_user.can_select_namespace? - .input-group-addon - = root_url - = f.select :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), {}, { class: 'select2 js-select-namespace', tabindex: 1} - - - else - .input-group-addon.static-namespace - #{root_url}#{current_user.username}/ - = f.hidden_field :namespace_id, value: current_user.namespace_id - .form-group.col-xs-12.col-sm-6.project-path - = f.label :path, class: 'label-light' do - %span - Project name - = f.text_field :path, placeholder: "my-awesome-project", class: "form-control", tabindex: 2, autofocus: true, required: true - - if current_user.can_create_group? - .help-block - Want to house several dependent projects under the same namespace? - = link_to "Create a group", new_group_path - - .form-group - = f.label :description, class: 'label-light' do - Project description - %span.light (optional) - = f.text_area :description, placeholder: 'Description format', class: "form-control", rows: 3, maxlength: 250 - - .form-group.visibility-level-setting - = f.label :visibility_level, class: 'label-light' do - Visibility Level - = link_to icon('question-circle'), help_page_path("public_access/public_access"), aria: { label: 'Documentation for Visibility Level' } - = render 'shared/visibility_level', f: f, visibility_level: visibility_level.to_i, can_change_visibility_level: true, form_model: @project, with_label: false - - = f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4 - = link_to 'Cancel', dashboard_projects_path, class: 'btn btn-cancel' + .col-lg-12 + .js-toggle-content.hide + %hr + = render "shared/import_form", f: f .save-project-loader.hide .center diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index 25153fd0b6f..fd5d3ec56da 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -17,14 +17,14 @@ %i Owners .light - if can?(current_user, :admin_project_member, @project) - %ul.nav-links.project-member-tabs{ role: 'tablist' } + %ul.nav-links.gitlab-tabs{ role: 'tablist' } %li.active{ role: 'presentation' } %a{ href: '#add-member-pane', id: 'add-member-tab', data: { toggle: 'tab' }, role: 'tab' } Add member - if @project.allowed_to_share_with_group? %li{ role: 'presentation' } %a{ href: '#share-with-group-pane', id: 'share-with-group-tab', data: { toggle: 'tab' }, role: 'tab' } Share with group - .tab-content.project-member-tab-content + .tab-content.gitlab-tab-content .tab-pane.active{ id: 'add-member-pane', role: 'tabpanel' } = render 'projects/project_members/new_project_member', tab_title: 'Add member' .tab-pane{ id: 'share-with-group-pane', role: 'tabpanel' } diff --git a/app/views/shared/icons/_express.svg b/app/views/shared/icons/_express.svg index f2c94319f19..a51e81e5568 100644 --- a/app/views/shared/icons/_express.svg +++ b/app/views/shared/icons/_express.svg @@ -1,6 +1 @@ - - - - - - + diff --git a/app/views/shared/icons/_rails.svg b/app/views/shared/icons/_rails.svg index 0bb09a705df..852bd183cc7 100644 --- a/app/views/shared/icons/_rails.svg +++ b/app/views/shared/icons/_rails.svg @@ -1,6 +1 @@ - - - - - - + diff --git a/app/views/shared/icons/_spring.svg b/app/views/shared/icons/_spring.svg index 508349aa456..ccf18749029 100644 --- a/app/views/shared/icons/_spring.svg +++ b/app/views/shared/icons/_spring.svg @@ -1,6 +1 @@ - - - - - - + diff --git a/lib/gitlab/project_template.rb b/lib/gitlab/project_template.rb index 732fbf68dad..0b43377a579 100644 --- a/lib/gitlab/project_template.rb +++ b/lib/gitlab/project_template.rb @@ -1,9 +1,9 @@ module Gitlab class ProjectTemplate - attr_reader :title, :name + attr_reader :title, :name, :description, :preview - def initialize(name, title) - @name, @title = name, title + def initialize(name, title, description, preview) + @name, @title, @description, @preview = name, title, description, preview end alias_method :logo, :name @@ -25,9 +25,9 @@ module Gitlab end TEMPLATES_TABLE = [ - ProjectTemplate.new('rails', 'Ruby on Rails'), - ProjectTemplate.new('spring', 'Spring'), - ProjectTemplate.new('express', 'NodeJS Express') + ProjectTemplate.new('rails', 'Ruby on Rails', 'Includes a MVC structure, gemfile, rakefile, and .gitlab-ci.yml file, along with many others, to help you get started.', 'https://gitlab.com/gitlab-org/project-templates/rails'), + ProjectTemplate.new('spring', 'Spring', 'Includes a MVC structure, mvnw, pom.xml, and .gitlab-ci.yml file to help you get started.', 'https://gitlab.com/gitlab-org/project-templates/spring'), + ProjectTemplate.new('express', 'NodeJS Express', 'Includes a MVC structure, and .gitlab-ci.yml file to help you get started.', 'https://gitlab.com/gitlab-org/project-templates/express') ].freeze class << self diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index c928459f911..026aa03f7cf 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -27,6 +27,7 @@ feature 'Import/Export - project import integration test', :js do select2(namespace.id, from: '#project_namespace_id') fill_in :project_path, with: project_path, visible: true + click_import_project_tab click_link 'GitLab export' expect(page).to have_content('Import an exported GitLab project') @@ -51,6 +52,7 @@ feature 'Import/Export - project import integration test', :js do context 'path is not prefilled' do scenario 'user imports an exported project successfully' do visit new_project_path + click_import_project_tab click_link 'GitLab export' fill_in :path, with: 'test-project-path', visible: true @@ -72,6 +74,7 @@ feature 'Import/Export - project import integration test', :js do select2(user.namespace.id, from: '#project_namespace_id') fill_in :project_path, with: project.name, visible: true + click_import_project_tab click_link 'GitLab export' attach_file('file', file) click_on 'Import project' @@ -81,19 +84,6 @@ feature 'Import/Export - project import integration test', :js do end end - context 'when limited to the default user namespace' do - scenario 'passes correct namespace ID in the URL' do - visit new_project_path - - fill_in :project_path, with: 'test-project-path', visible: true - - click_link 'GitLab export' - - expect(page).to have_content('GitLab project export') - expect(URI.parse(current_url).query).to eq("namespace_id=#{user.namespace.id}&path=test-project-path") - end - end - def wiki_exists?(project) wiki = ProjectWiki.new(project) File.exist?(wiki.repository.path_to_repo) && !wiki.repository.empty? @@ -102,4 +92,8 @@ feature 'Import/Export - project import integration test', :js do def project_hook_exists?(project) Gitlab::Git::Hook.new('post-receive', project.repository.raw_repository).exists? end + + def click_import_project_tab + find('#import-project-tab').trigger('click') + end end diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb index cd3dc72d3c6..8e11cb94350 100644 --- a/spec/features/projects/new_project_spec.rb +++ b/spec/features/projects/new_project_spec.rb @@ -9,12 +9,14 @@ feature 'New project' do sign_in(user) end - it 'shows "New project" page' do + it 'shows "New project" page', :js do visit new_project_path expect(page).to have_content('Project path') expect(page).to have_content('Project name') + find('#import-project-tab').trigger('click') + expect(page).to have_link('GitHub') expect(page).to have_link('Bitbucket') expect(page).to have_link('GitLab.com') @@ -23,14 +25,15 @@ feature 'New project' do expect(page).to have_link('GitLab export') end - context 'Visibility level selector' do + context 'Visibility level selector', :js do Gitlab::VisibilityLevel.options.each do |key, level| it "sets selector to #{key}" do stub_application_setting(default_project_visibility: level) visit new_project_path - - expect(find_field("project_visibility_level_#{level}")).to be_checked + page.within('#blank-project-pane') do + expect(find_field("project_visibility_level_#{level}")).to be_checked + end end it "saves visibility level #{level} on validation error" do @@ -38,8 +41,9 @@ feature 'New project' do choose(s_(key)) click_button('Create project') - - expect(find_field("project_visibility_level_#{level}")).to be_checked + page.within('#blank-project-pane') do + expect(find_field("project_visibility_level_#{level}")).to be_checked + end end end end @@ -51,9 +55,11 @@ feature 'New project' do end it 'selects the user namespace' do - namespace = find('#project_namespace_id') + page.within('#blank-project-pane') do + namespace = find('#project_namespace_id') - expect(namespace.text).to eq user.username + expect(namespace.text).to eq user.username + end end end @@ -66,9 +72,11 @@ feature 'New project' do end it 'selects the group namespace' do - namespace = find('#project_namespace_id option[selected]') + page.within('#blank-project-pane') do + namespace = find('#project_namespace_id option[selected]') - expect(namespace.text).to eq group.name + expect(namespace.text).to eq group.name + end end end @@ -82,9 +90,11 @@ feature 'New project' do end it 'selects the group namespace' do - namespace = find('#project_namespace_id option[selected]') + page.within('#blank-project-pane') do + namespace = find('#project_namespace_id option[selected]') - expect(namespace.text).to eq subgroup.full_path + expect(namespace.text).to eq subgroup.full_path + end end end @@ -124,9 +134,10 @@ feature 'New project' do end end - context 'Import project options' do + context 'Import project options', :js do before do visit new_project_path + find('#import-project-tab').trigger('click') end context 'from git repository url' do diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index ac62280e4ca..3bc7ec3123f 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -12,8 +12,9 @@ feature 'Project' do visit new_project_path end - it "allows creation from templates" do - page.choose(template.name) + it "allows creation from templates", :js do + find('#create-from-template-tab').trigger('click') + find("##{template.name}").trigger('click') fill_in("project_path", with: template.name) page.within '#content-body' do diff --git a/spec/lib/gitlab/project_template_spec.rb b/spec/lib/gitlab/project_template_spec.rb index d19bd611919..57b0ef8d1ad 100644 --- a/spec/lib/gitlab/project_template_spec.rb +++ b/spec/lib/gitlab/project_template_spec.rb @@ -4,9 +4,9 @@ describe Gitlab::ProjectTemplate do describe '.all' do it 'returns a all templates' do expected = [ - described_class.new('rails', 'Ruby on Rails'), - described_class.new('spring', 'Spring'), - described_class.new('express', 'NodeJS Express') + described_class.new('rails', 'Ruby on Rails', 'Includes an MVC structure, .gitignore, Gemfile, and more great stuff', 'https://gitlab.com/gitlab-org/project-templates/rails'), + described_class.new('spring', 'Spring', 'Includes an MVC structure, .gitignore, Gemfile, and more great stuff', 'https://gitlab.com/gitlab-org/project-templates/spring'), + described_class.new('express', 'NodeJS Express', 'Includes an MVC structure, .gitignore, Gemfile, and more great stuff', 'https://gitlab.com/gitlab-org/project-templates/express') ] expect(described_class.all).to be_an(Array) @@ -31,7 +31,7 @@ describe Gitlab::ProjectTemplate do end describe 'instance methods' do - subject { described_class.new('phoenix', 'Phoenix Framework') } + subject { described_class.new('phoenix', 'Phoenix Framework', 'Phoenix description', 'link-to-template') } it { is_expected.to respond_to(:logo, :file, :archive_path) } end -- GitLab From 865d5d0423221c4528b8aeae88f4cad15c64e5e9 Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Thu, 12 Oct 2017 08:05:49 +0000 Subject: [PATCH 010/149] Merge branch '39028-repo-by-url-fields' into 'master' Add project fields to import project by url Closes #39028 See merge request gitlab-org/gitlab-ce!14822 --- app/assets/stylesheets/pages/projects.scss | 6 +- app/views/projects/new.html.haml | 94 +++++++++++----------- lib/gitlab/project_template.rb | 6 +- 3 files changed, 56 insertions(+), 50 deletions(-) diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 61dc9f13d50..bd385db9692 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -634,10 +634,14 @@ a.deploy-project-label { } .project-import { - .form-group { + .import-btn-container { margin-bottom: 0; } + .toggle-import-form { + padding-bottom: 10px; + } + .import-buttons { padding-left: 0; display: -webkit-flex; diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 0934c47a8e2..0a835dcdeb0 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -48,52 +48,54 @@ .tab-pane.import-project-pane{ id: 'import-project-pane', role: 'tabpanel' } = form_for @project, html: { class: 'new_project' } do |f| - if import_sources_enabled? - .project-import - .form-group.clearfix - = f.label :visibility_level, class: 'label-light' do #the label here seems wrong - Import project from - .col-sm-12.import-buttons - %div - - if github_import_enabled? - = link_to new_import_github_path, class: 'btn import_github' do - = icon('github', text: 'GitHub') - %div - - if bitbucket_import_enabled? - = link_to status_import_bitbucket_path, class: "btn import_bitbucket #{'how_to_import_link' unless bitbucket_import_configured?}" do - = icon('bitbucket', text: 'Bitbucket') - - unless bitbucket_import_configured? - = render 'bitbucket_import_modal' - %div - - if gitlab_import_enabled? - = link_to status_import_gitlab_path, class: "btn import_gitlab #{'how_to_import_link' unless gitlab_import_configured?}" do - = icon('gitlab', text: 'GitLab.com') - - unless gitlab_import_configured? - = render 'gitlab_import_modal' - %div - - if google_code_import_enabled? - = link_to new_import_google_code_path, class: 'btn import_google_code' do - = icon('google', text: 'Google Code') - %div - - if fogbugz_import_enabled? - = link_to new_import_fogbugz_path, class: 'btn import_fogbugz' do - = icon('bug', text: 'Fogbugz') - %div - - if gitea_import_enabled? - = link_to new_import_gitea_url, class: 'btn import_gitea' do - = custom_icon('go_logo') - Gitea - %div - - if git_import_enabled? - %button.btn.js-toggle-button.import_git{ type: "button" } - = icon('git', text: 'Repo by URL') - - if gitlab_project_import_enabled? - .import_gitlab_project.has-tooltip{ data: { container: 'body' } } - = link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit' do - = icon('gitlab', text: 'GitLab export') - .col-lg-12 - .js-toggle-content.hide - %hr - = render "shared/import_form", f: f + .project-import.row + .col-sm-12 + .form-group.import-btn-container.clearfix + = f.label :visibility_level, class: 'label-light' do #the label here seems wrong + Import project from + .import-buttons + %div + - if github_import_enabled? + = link_to new_import_github_path, class: 'btn import_github' do + = icon('github', text: 'GitHub') + %div + - if bitbucket_import_enabled? + = link_to status_import_bitbucket_path, class: "btn import_bitbucket #{'how_to_import_link' unless bitbucket_import_configured?}" do + = icon('bitbucket', text: 'Bitbucket') + - unless bitbucket_import_configured? + = render 'bitbucket_import_modal' + %div + - if gitlab_import_enabled? + = link_to status_import_gitlab_path, class: "btn import_gitlab #{'how_to_import_link' unless gitlab_import_configured?}" do + = icon('gitlab', text: 'GitLab.com') + - unless gitlab_import_configured? + = render 'gitlab_import_modal' + %div + - if google_code_import_enabled? + = link_to new_import_google_code_path, class: 'btn import_google_code' do + = icon('google', text: 'Google Code') + %div + - if fogbugz_import_enabled? + = link_to new_import_fogbugz_path, class: 'btn import_fogbugz' do + = icon('bug', text: 'Fogbugz') + %div + - if gitea_import_enabled? + = link_to new_import_gitea_url, class: 'btn import_gitea' do + = custom_icon('go_logo') + Gitea + %div + - if git_import_enabled? + %button.btn.js-toggle-button.import_git{ type: "button" } + = icon('git', text: 'Repo by URL') + - if gitlab_project_import_enabled? + .import_gitlab_project.has-tooltip{ data: { container: 'body' } } + = link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit' do + = icon('gitlab', text: 'GitLab export') + .col-lg-12 + .js-toggle-content.hide.toggle-import-form + %hr + = render "shared/import_form", f: f + = render 'new_project_fields', f: f, project_name_id: "import-url-name" .save-project-loader.hide .center diff --git a/lib/gitlab/project_template.rb b/lib/gitlab/project_template.rb index 0b43377a579..ae136202f0c 100644 --- a/lib/gitlab/project_template.rb +++ b/lib/gitlab/project_template.rb @@ -25,9 +25,9 @@ module Gitlab end TEMPLATES_TABLE = [ - ProjectTemplate.new('rails', 'Ruby on Rails', 'Includes a MVC structure, gemfile, rakefile, and .gitlab-ci.yml file, along with many others, to help you get started.', 'https://gitlab.com/gitlab-org/project-templates/rails'), - ProjectTemplate.new('spring', 'Spring', 'Includes a MVC structure, mvnw, pom.xml, and .gitlab-ci.yml file to help you get started.', 'https://gitlab.com/gitlab-org/project-templates/spring'), - ProjectTemplate.new('express', 'NodeJS Express', 'Includes a MVC structure, and .gitlab-ci.yml file to help you get started.', 'https://gitlab.com/gitlab-org/project-templates/express') + ProjectTemplate.new('rails', 'Ruby on Rails', 'Includes an MVC structure, gemfile, rakefile, and .gitlab-ci.yml file, along with many others, to help you get started.', 'https://gitlab.com/gitlab-org/project-templates/rails'), + ProjectTemplate.new('spring', 'Spring', 'Includes an MVC structure, mvnw, pom.xml, and .gitlab-ci.yml file to help you get started.', 'https://gitlab.com/gitlab-org/project-templates/spring'), + ProjectTemplate.new('express', 'NodeJS Express', 'Includes an MVC structure and .gitlab-ci.yml file to help you get started.', 'https://gitlab.com/gitlab-org/project-templates/express') ].freeze class << self -- GitLab From 9bbe89e1ccaa70bf191b1a15ce18ead03a470f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 12 Oct 2017 17:37:22 +0000 Subject: [PATCH 011/149] Merge branch 'update-licenses.csv' into 'master' Update dependencies license list See merge request gitlab-org/gitlab-ce!14845 --- vendor/licenses.csv | 154 +++++++++++++++----------------------------- 1 file changed, 52 insertions(+), 102 deletions(-) diff --git a/vendor/licenses.csv b/vendor/licenses.csv index 24623ff4c1f..9f78059986d 100644 --- a/vendor/licenses.csv +++ b/vendor/licenses.csv @@ -13,9 +13,9 @@ activemodel,4.2.8,MIT activerecord,4.2.8,MIT activesupport,4.2.8,MIT acts-as-taggable-on,4.0.0,MIT -addressable,2.3.8,Apache 2.0 +addressable,2.5.2,Apache 2.0 after,0.8.2,MIT -ajv,5.2.0,MIT +ajv,5.2.2,MIT ajv-keywords,2.1.0,MIT akismet,2.0.0,MIT align-text,0.1.4,MIT @@ -28,8 +28,6 @@ ansi-regex,2.1.1,MIT ansi-styles,2.2.1,MIT anymatch,1.3.2,ISC append-transform,0.4.0,MIT -aproba,1.1.1,ISC -are-we-there-yet,1.1.4,ISC arel,6.0.4,MIT argparse,1.0.9,MIT arr-diff,2.0.0,MIT @@ -46,21 +44,15 @@ arrify,1.0.1,MIT asana,0.6.0,MIT asciidoctor,1.5.3,MIT asciidoctor-plantuml,0.0.7,MIT -asn1,0.2.3,MIT asn1.js,4.9.1,MIT assert,1.4.1,MIT -assert-plus,0.2.0,MIT async,2.4.1,MIT async-each,1.0.1,MIT -asynckit,0.4.0,MIT atomic,1.1.99,Apache 2.0 attr_encrypted,3.0.3,MIT attr_required,1.0.0,MIT -autoparse,0.3.3,Apache 2.0 autoprefixer,6.7.7,MIT autoprefixer-rails,6.2.3,MIT -aws-sign2,0.6.0,Apache 2.0 -aws4,1.6.0,MIT axiom-types,0.1.1,MIT axios,0.16.2,MIT babel-code-frame,6.22.0,MIT @@ -145,19 +137,16 @@ base64-js,1.2.0,MIT base64id,1.0.0,MIT batch,0.6.1,MIT bcrypt,3.1.11,MIT -bcrypt-pbkdf,1.0.1,New BSD bcrypt_pbkdf,1.0.0,MIT better-assert,1.0.2,MIT big.js,3.1.3,MIT binary-extensions,1.10.0,MIT -bindata,2.3.5,ruby +bindata,2.4.1,ruby blob,0.0.4,unknown -block-stream,0.0.9,ISC bluebird,2.11.0,MIT bn.js,4.11.6,MIT body-parser,1.17.2,MIT bonjour,3.5.0,MIT -boom,2.10.1,New BSD bootstrap-sass,3.3.6,MIT bootstrap_form,2.7.0,MIT brace-expansion,1.1.8,MIT @@ -187,7 +176,6 @@ camelcase-keys,2.1.0,MIT caniuse-api,1.6.1,MIT caniuse-db,1.0.30000649,CC-BY-4.0 carrierwave,1.1.0,MIT -caseless,0.12.0,Apache 2.0 cause,0.1,MIT center-align,0.1.3,MIT chalk,1.1.3,MIT @@ -216,7 +204,6 @@ color-string,0.3.0,MIT colormin,1.1.2,MIT colors,1.1.2,MIT combine-lists,1.0.1,MIT -combined-stream,1.0.5,MIT commander,2.9.0,MIT commondir,1.0.1,MIT component-bind,1.0.0,unknown @@ -233,8 +220,7 @@ configstore,1.4.0,Simplified BSD connect,3.6.3,MIT connect-history-api-fallback,1.3.0,MIT connection_pool,2.2.1,MIT -console-browserify,1.1.0,MIT -console-control-strings,1.1.0,ISC +console-browserify,1.1.0,[Circular] consolidate,0.14.5,MIT constants-browserify,1.0.0,MIT contains-path,0.1.0,MIT @@ -254,7 +240,6 @@ create-hmac,1.1.4,MIT creole,0.5.0,ruby cropper,2.3.0,MIT cross-spawn,5.1.0,MIT -cryptiles,2.0.5,New BSD crypto-browserify,3.11.0,MIT css-color-names,0.0.4,MIT css-loader,0.28.0,MIT @@ -268,13 +253,14 @@ custom-event,1.0.1,MIT d,1.0.0,MIT d3,3.5.11,New BSD d3_rails,3.5.11,MIT -dashdash,1.14.1,MIT date-now,0.1.4,MIT de-indent,1.0.2,MIT debug,2.6.8,MIT debugger-ruby_core_source,1.3.8,MIT decamelize,1.2.0,MIT deckar01-task_list,2.0.0,MIT +declarative,0.0.10,MIT +declarative-option,0.1.0,MIT decompress-response,3.3.0,MIT deep-equal,1.0.1,MIT deep-extend,0.4.2,MIT @@ -283,9 +269,7 @@ default-require-extensions,1.0.0,MIT default_value_for,3.0.2,MIT defined,1.0.0,MIT del,2.2.2,MIT -delayed-stream,1.0.0,MIT delegate,3.1.2,MIT -delegates,1.0.0,MIT depd,1.1.1,MIT des.js,1.0.0,MIT descendants_tracker,0.0.4,MIT @@ -310,14 +294,13 @@ domain_name,0.5.20161021,"Simplified BSD,New BSD,Mozilla Public License 2.0" domelementtype,1.3.0,unknown domhandler,2.3.0,unknown domutils,1.5.1,unknown -doorkeeper,4.2.0,MIT -doorkeeper-openid_connect,1.1.2,MIT +doorkeeper,4.2.6,MIT +doorkeeper-openid_connect,1.2.0,MIT dropzone,4.2.0,MIT dropzonejs-rails,0.7.2,MIT -duplexer,0.1.1,MIT +duplexer,0.1.1,[Circular] duplexer3,0.1.4,New BSD duplexify,3.5.1,MIT -ecc-jsbn,0.1.1,MIT editorconfig,0.13.2,MIT ee-first,1.1.1,MIT ejs,2.5.6,Apache 2.0 @@ -362,7 +345,7 @@ eslint-plugin-import,2.2.0,MIT eslint-plugin-jasmine,2.2.0,MIT eslint-plugin-promise,3.5.0,ISC espree,3.5.0,Simplified BSD -esprima,4.0.0,Simplified BSD +esprima,2.7.3,Simplified BSD esquery,1.0.0,BSD esrecurse,4.1.0,Simplified BSD estraverse,4.1.1,Simplified BSD @@ -388,12 +371,10 @@ express,4.15.4,MIT expression_parser,0.9.0,MIT extend,3.0.1,MIT extglob,0.3.2,MIT -extlib,0.9.16,MIT -extsprintf,1.0.2,MIT -faraday,0.12.1,MIT +faraday,0.12.2,MIT faraday_middleware,0.11.0.1,MIT faraday_middleware-multi_json,0.0.6,MIT -fast-deep-equal,0.1.0,MIT +fast-deep-equal,1.0.0,MIT fast-levenshtein,2.0.6,MIT fast_gettext,1.4.0,"MIT,ruby" fastparse,1.1.1,MIT @@ -428,8 +409,6 @@ follow-redirects,1.2.3,MIT font-awesome-rails,4.7.0.1,"MIT,SIL Open Font License" for-in,0.1.6,MIT for-own,0.1.4,MIT -forever-agent,0.6.1,Apache 2.0 -form-data,2.1.4,MIT formatador,0.2.5,MIT forwarded,0.1.0,MIT fresh,0.5.0,MIT @@ -437,11 +416,8 @@ from,0.1.7,MIT fs-access,1.0.1,MIT fs-extra,0.26.7,MIT fs.realpath,1.0.0,ISC -fsevents,1.1.2,MIT -fstream,1.0.11,ISC -fstream-ignore,1.0.5,ISC +fsevents,,unknown function-bind,1.1.0,MIT -gauge,2.7.4,ISC gemnasium-gitlab-service,0.2.6,MIT gemojione,3.3.0,MIT generate-function,2.0.0,MIT @@ -450,15 +426,15 @@ get-caller-file,1.0.2,ISC get-stdin,4.0.1,MIT get-stream,3.0.0,MIT get_process_mem,0.2.0,MIT -getpass,0.1.7,MIT gettext_i18n_rails,1.8.0,MIT gettext_i18n_rails_js,1.2.0,MIT -gitaly-proto,0.33.0,MIT +gitaly-proto,0.41.0,MIT github-linguist,4.7.6,MIT github-markup,1.6.1,MIT gitlab-flowdock-git-hook,1.0.1,MIT -gitlab-grit,2.8.1,MIT -gitlab-markup,1.5.1,MIT +gitlab-grit,2.8.2,MIT +gitlab-markup,1.6.2,MIT +gitlab-svgs,1.0.4,unknown gitlab_omniauth-ldap,2.0.4,MIT glob,6.0.4,ISC glob-base,0.3.0,MIT @@ -471,9 +447,9 @@ gollum-lib,4.2.7,MIT gollum-rugged_adapter,0.4.4,MIT gon,6.1.0,MIT good-listener,1.2.2,MIT -google-api-client,0.8.7,Apache 2.0 +google-api-client,0.13.6,Apache 2.0 google-protobuf,3.4.0.2,New BSD -googleauth,0.5.1,Apache 2.0 +googleauth,0.5.3,Apache 2.0 got,7.1.0,MIT gpgme,2.0.13,LGPL-2.1+ graceful-fs,4.1.11,ISC @@ -481,14 +457,12 @@ graceful-readlink,1.0.1,MIT grape,1.0.0,MIT grape-entity,0.6.0,MIT grape-route-helpers,2.1.0,MIT -grape_logging,1.6.0,MIT -grpc,1.4.5,New BSD +grape_logging,1.7.0,MIT +grpc,1.6.0,Apache 2.0 gzip-size,3.0.0,MIT hamlit,2.6.1,MIT handle-thing,1.2.5,MIT handlebars,4.0.6,MIT -har-schema,1.0.5,ISC -har-validator,4.2.1,ISC has,1.0.1,MIT has-ansi,2.0.0,MIT has-binary,0.1.7,MIT @@ -496,16 +470,13 @@ has-cors,1.1.0,MIT has-flag,2.0.0,MIT has-symbol-support-x,1.3.0,MIT has-to-string-tag-x,1.3.0,MIT -has-unicode,2.0.1,ISC hash-sum,1.0.2,MIT hash.js,1.0.3,MIT hashie,3.5.6,MIT hashie-forbidden_attributes,0.1.1,MIT -hawk,3.1.3,New BSD he,1.1.1,MIT health_check,2.6.0,MIT hipchat,1.5.2,MIT -hoek,2.16.3,New BSD home-or-tmp,2.0.0,MIT hosted-git-info,2.2.0,ISC hpack.js,2.1.6,MIT @@ -522,7 +493,6 @@ http-errors,1.6.2,MIT http-form_data,1.0.1,MIT http-proxy,1.16.2,MIT http-proxy-middleware,0.17.4,MIT -http-signature,1.1.1,MIT http_parser.rb,0.6.0,MIT httparty,0.13.7,MIT httpclient,2.8.2,ruby @@ -583,15 +553,13 @@ is-resolvable,1.0.0,MIT is-retry-allowed,1.1.0,MIT is-stream,1.1.0,MIT is-svg,2.1.0,MIT -is-typedarray,1.0.0,MIT is-unc-path,0.1.2,MIT is-utf8,0.2.1,MIT is-windows,0.2.0,MIT isarray,1.0.0,MIT isbinaryfile,3.0.2,MIT -isexe,1.1.2,ISC +isexe,2.0.0,ISC isobject,2.1.0,MIT -isstream,0.1.2,MIT istanbul,0.4.5,New BSD istanbul-api,1.1.1,New BSD istanbul-lib-coverage,1.0.1,New BSD @@ -605,7 +573,6 @@ jasmine-core,2.6.3,MIT jasmine-jquery,2.1.1,MIT jed,1.1.1,MIT jira-ruby,1.4.1,MIT -jodid25519,1.0.2,MIT jquery,2.2.1,MIT jquery-atwho-rails,1.3.2,MIT jquery-rails,4.1.1,MIT @@ -615,21 +582,18 @@ js-beautify,1.6.12,MIT js-cookie,2.1.3,MIT js-tokens,3.0.1,MIT js-yaml,3.7.0,MIT -jsbn,0.1.1,MIT jsesc,1.3.0,MIT json,1.8.6,ruby -json-jwt,1.7.1,MIT +json-jwt,1.7.2,MIT json-loader,0.5.7,MIT -json-schema,0.2.3,"AFLv2.1,BSD" json-schema-traverse,0.3.1,MIT json-stable-stringify,1.0.1,MIT json-stringify-safe,5.0.1,ISC -json3,3.3.2,MIT +json3,3.3.2,[Circular] json5,0.5.1,MIT jsonfile,2.4.0,MIT jsonify,0.0.0,Public Domain jsonpointer,4.0.1,MIT -jsprim,1.4.0,MIT jszip,3.1.3,(MIT OR GPL-3.0) jszip-utils,0.0.2,MIT or GPLv3 jwt,1.5.6,MIT @@ -649,7 +613,6 @@ kind-of,3.1.0,MIT klaw,1.3.1,MIT kubeclient,2.2.0,MIT latest-version,1.0.1,MIT -launchy,2.4.3,ISC lazy-cache,1.0.4,MIT lcid,1.0.0,MIT levn,0.3.0,MIT @@ -706,7 +669,7 @@ marked,0.3.6,MIT math-expression-evaluator,1.2.16,MIT media-typer,0.3.0,MIT mem,1.1.0,MIT -memoist,0.15.0,MIT +memoist,0.16.0,MIT memory-fs,0.4.1,MIT meow,3.7.0,MIT merge-descriptors,1.0.1,MIT @@ -714,13 +677,14 @@ method_source,0.8.2,MIT methods,1.1.2,MIT micromatch,2.3.11,MIT miller-rabin,4.0.0,MIT -mime,1.3.4,MIT -mime-db,1.27.0,MIT -mime-types,2.99.3,"MIT,Artistic-2.0,GPL-2.0" +mime,1.3.4,[Circular] +mime-db,1.29.0,MIT +mime-types,3.1,MIT +mime-types-data,3.2016.0521,MIT mimemagic,0.3.0,MIT mimic-fn,1.1.0,MIT mimic-response,1.0.0,MIT -mini_portile2,2.2.0,MIT +mini_portile2,2.3.0,MIT minimalistic-assert,1.0.0,ISC minimatch,3.0.3,ISC minimist,0.0.8,MIT @@ -731,7 +695,7 @@ monaco-editor,0.8.3,MIT mousetrap,1.4.6,Apache 2.0 mousetrap-rails,1.4.6,"MIT,Apache" ms,2.0.0,MIT -multi_json,1.12.1,MIT +multi_json,1.12.2,MIT multi_xml,0.6.0,MIT multicast-dns,6.1.1,MIT multicast-dns-service-types,1.1.0,MIT @@ -739,9 +703,7 @@ multipart-post,2.0.0,MIT mustermann,1.0.0,MIT mustermann-grape,1.0.0,MIT mute-stream,0.0.5,ISC -mysql2,0.4.5,MIT name-all-modules-plugin,1.0.1,MIT -nan,2.6.2,MIT natural-compare,1.4.0,MIT negotiator,0.6.1,MIT nested-error-stacks,1.0.2,MIT @@ -751,22 +713,19 @@ netrc,0.11.0,MIT node-dir,0.1.17,MIT node-forge,0.6.33,BSD node-libs-browser,2.0.0,MIT -node-pre-gyp,0.6.36,New BSD nodemon,1.11.0,MIT -nokogiri,1.8.0,MIT +nokogiri,1.8.1,MIT nopt,3.0.6,ISC -normalize-package-data,2.4.0,Simplified BSD +normalize-package-data,2.3.5,Simplified BSD normalize-path,2.1.1,MIT normalize-range,0.1.2,MIT normalize-url,1.9.1,MIT npm-run-path,2.0.2,MIT -npmlog,4.1.0,ISC null-check,1.0.0,MIT num2fraction,1.2.2,MIT number-is-nan,1.0.1,MIT numerizer,0.1.1,MIT oauth,0.5.1,MIT -oauth-sign,0.8.2,Apache 2.0 oauth2,1.4.0,MIT object-assign,4.1.1,MIT object-component,0.0.3,unknown @@ -777,7 +736,7 @@ oj,2.17.5,MIT omniauth,1.4.2,MIT omniauth-auth0,1.4.1,MIT omniauth-authentiq,0.3.1,MIT -omniauth-azure-oauth2,0.0.6,MIT +omniauth-azure-oauth2,0.0.9,MIT omniauth-cas3,1.1.4,MIT omniauth-facebook,4.0.0,MIT omniauth-github,1.1.2,MIT @@ -786,7 +745,7 @@ omniauth-google-oauth2,0.5.2,MIT omniauth-kerberos,0.3.0,MIT omniauth-multipassword,0.4.2,MIT omniauth-oauth,1.1.0,MIT -omniauth-oauth2,1.3.1,MIT +omniauth-oauth2,1.4.0,MIT omniauth-oauth2-generic,0.2.2,MIT omniauth-saml,1.7.0,MIT omniauth-shibboleth,1.2.1,MIT @@ -839,13 +798,11 @@ pbkdf2,3.0.9,MIT peek,1.0.1,MIT peek-gc,0.0.2,MIT peek-host,1.0.0,MIT -peek-mysql2,1.1.0,MIT peek-performance_bar,1.3.0,MIT peek-pg,1.3.0,MIT peek-rblineprof,0.2.0,MIT peek-redis,1.2.0,MIT peek-sidekiq,1.0.3,MIT -performance-now,0.2.0,MIT pg,0.18.4,"BSD,ruby,GPL" pify,2.3.0,MIT pikaday,1.5.1,"BSD,MIT" @@ -910,6 +867,7 @@ prr,0.0.0,MIT ps-tree,1.1.0,MIT pseudomap,1.0.2,ISC public-encrypt,4.0.0,MIT +public_suffix,3.0.0,MIT punycode,1.4.1,MIT pyu-ruby-sasl,0.0.3.3,MIT q,1.5.0,MIT @@ -917,7 +875,7 @@ qjobs,1.1.5,MIT qs,6.5.0,New BSD query-string,4.3.2,MIT querystring,0.2.0,MIT -querystring-es3,0.2.1,MIT +querystring-es3,0.2.1,[Circular] querystringify,0.0.4,MIT rack,1.6.8,MIT rack-accept,0.4.5,MIT @@ -935,7 +893,7 @@ rails-i18n,4.0.9,MIT railties,4.2.8,MIT rainbow,2.2.2,MIT raindrops,0.18.0,LGPL-2.1+ -rake,12.0.0,MIT +rake,12.1.0,MIT randomatic,1.1.6,MIT randombytes,2.0.3,MIT range-parser,1.2.0,MIT @@ -982,7 +940,7 @@ remove-trailing-separator,1.1.0,ISC repeat-element,1.1.2,MIT repeat-string,1.6.1,MIT repeating,2.0.1,MIT -request,2.81.0,Apache 2.0 +representable,3.0.4,MIT request_store,1.3.1,MIT require-directory,2.1.1,MIT require-from-string,1.2.1,MIT @@ -994,7 +952,7 @@ resolve-from,1.0.1,MIT responders,2.3.0,MIT rest-client,2.0.0,MIT restore-cursor,1.0.1,MIT -retriable,1.4.1,MIT +retriable,3.1.1,MIT right-align,0.1.3,MIT rimraf,2.6.1,ISC rinku,2.0.0,ISC @@ -1013,7 +971,7 @@ rufus-scheduler,3.4.0,MIT rugged,0.26.0,MIT run-async,0.1.0,MIT rx-lite,3.1.2,Apache 2.0 -safe-buffer,5.1.1,MIT +safe-buffer,5.0.1,MIT safe_yaml,1.0.4,MIT sanitize,2.1.0,MIT sass,3.4.22,MIT @@ -1053,7 +1011,6 @@ slack-notifier,1.5.1,MIT slash,1.0.0,MIT slice-ansi,0.0.4,MIT slide,1.1.6,ISC -sntp,1.0.9,BSD socket.io,1.7.3,MIT socket.io-adapter,0.5.0,MIT socket.io-client,1.7.3,MIT @@ -1074,7 +1031,6 @@ sprintf-js,1.0.3,New BSD sprockets,3.7.1,MIT sprockets-rails,3.2.0,MIT sql.js,0.4.0,MIT -sshpk,1.13.0,MIT state_machines,0.4.0,MIT state_machines-activemodel,0.4.0,MIT state_machines-activerecord,0.4.0,MIT @@ -1085,22 +1041,20 @@ stream-http,2.6.3,MIT stream-shift,1.0.0,MIT strict-uri-encode,1.1.0,MIT string-length,1.0.1,MIT -string-width,2.0.0,MIT -string_decoder,1.0.3,MIT +string-width,1.0.2,MIT +string_decoder,0.10.31,MIT stringex,2.7.1,MIT -stringstream,0.0.5,MIT strip-ansi,3.0.1,MIT strip-bom,3.0.0,MIT strip-eof,1.0.0,MIT strip-indent,1.0.1,MIT strip-json-comments,2.0.1,MIT -supports-color,4.2.1,MIT +supports-color,3.2.3,MIT +svg4everybody,2.1.9,CC0-1.0 svgo,0.7.2,MIT sys-filesystem,1.1.6,Artistic 2.0 table,3.8.3,New BSD tapable,0.2.8,MIT -tar,2.2.1,ISC -tar-pack,3.4.0,Simplified BSD temple,0.7.7,MIT test-exclude,4.0.0,ISC text,1.3.1,MIT @@ -1113,6 +1067,7 @@ three-stl-loader,1.0.4,MIT through,2.3.8,MIT thunky,0.1.0,unknown tilt,2.0.6,MIT +time-stamp,2.0.0,MIT timeago.js,2.0.5,MIT timed-out,4.0.1,MIT timers-browserify,2.0.4,MIT @@ -1124,31 +1079,28 @@ to-arraybuffer,1.0.1,MIT to-fast-properties,1.0.2,MIT toml-rb,0.3.15,MIT touch,1.0.0,ISC -tough-cookie,2.3.2,New BSD traverse,0.6.6,MIT trim-newlines,1.0.0,MIT trim-right,1.0.1,MIT truncato,0.7.10,MIT tryit,1.0.3,MIT tty-browserify,0.0.0,MIT -tunnel-agent,0.6.0,Apache 2.0 -tweetnacl,0.14.5,Unlicense type-check,0.3.2,MIT type-is,1.6.15,MIT typedarray,0.0.6,MIT tzinfo,1.2.3,MIT u2f,0.2.1,MIT +uber,0.1.0,MIT uglifier,2.7.2,MIT uglify-js,2.8.29,Simplified BSD uglify-to-browserify,1.0.2,MIT uglifyjs-webpack-plugin,0.4.6,MIT -uid-number,0.0.6,ISC ultron,1.1.0,MIT unc-path-regex,0.1.2,MIT undefsafe,0.0.3,MIT / http://rem.mit-license.org underscore,1.8.3,MIT unf,0.1.4,BSD -unf_ext,0.0.7.2,MIT +unf_ext,0.0.7.4,MIT unicorn,5.1.0,ruby unicorn-worker-killer,0.4.4,ruby uniq,1.0.1,MIT @@ -1166,13 +1118,12 @@ user-home,2.0.0,MIT useragent,2.2.1,MIT util,0.10.3,MIT util-deprecate,1.0.2,MIT -utils-merge,1.0.0,MIT -uuid,3.0.1,MIT +utils-merge,1.0.0,[Circular] +uuid,2.0.3,MIT validate-npm-package-license,3.0.1,Apache 2.0 validates_hostname,1.0.6,MIT vary,1.1.1,MIT vendors,1.0.1,MIT -verror,1.3.6,MIT version_sorter,2.1.0,MIT virtus,1.0.5,MIT visibilityjs,1.2.4,MIT @@ -1200,12 +1151,11 @@ webpack-stats-plugin,0.1.5,MIT websocket-driver,0.6.5,MIT websocket-extensions,0.1.1,MIT whet.extend,0.9.9,MIT -which,1.2.12,ISC +which,1.3.0,ISC which-module,2.0.0,ISC -wide-align,1.1.2,ISC wikicloth,0.8.1,MIT window-size,0.1.0,MIT -wordwrap,0.0.2,MIT/X11 +wordwrap,1.0.0,MIT wrap-ansi,2.1.0,MIT wrappy,1.0.2,ISC write,0.2.1,MIT -- GitLab From e281a13b2b07e2dcd3105fb5fa5d05fbf787168f Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 13 Oct 2017 11:10:47 +0000 Subject: [PATCH 012/149] Merge branch '39032-improve-merge-ongoing-check-consistency' into 'master' Make "merge ongoing" check more consistent Closes #39032 See merge request gitlab-org/gitlab-ce!14825 --- app/models/merge_request.rb | 2 +- ...mprove-merge-ongoing-check-consistency.yml | 5 +++++ lib/gitlab/sidekiq_status.rb | 7 ++++++ spec/lib/gitlab/sidekiq_status_spec.rb | 12 ++++++++++ spec/models/merge_request_spec.rb | 22 ++++++++++++++++++- 5 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 changelogs/unreleased/39032-improve-merge-ongoing-check-consistency.yml diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 292122f779e..4fc1a9d4ab8 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -392,7 +392,7 @@ class MergeRequest < ActiveRecord::Base end def merge_ongoing? - !!merge_jid && !merged? + !!merge_jid && !merged? && Gitlab::SidekiqStatus.running?(merge_jid) end def closed_without_fork? diff --git a/changelogs/unreleased/39032-improve-merge-ongoing-check-consistency.yml b/changelogs/unreleased/39032-improve-merge-ongoing-check-consistency.yml new file mode 100644 index 00000000000..361b6af196a --- /dev/null +++ b/changelogs/unreleased/39032-improve-merge-ongoing-check-consistency.yml @@ -0,0 +1,5 @@ +--- +title: Make "merge ongoing" check more consistent +merge_request: +author: +type: fixed diff --git a/lib/gitlab/sidekiq_status.rb b/lib/gitlab/sidekiq_status.rb index a0a2769cf9e..a1f689d94d9 100644 --- a/lib/gitlab/sidekiq_status.rb +++ b/lib/gitlab/sidekiq_status.rb @@ -51,6 +51,13 @@ module Gitlab self.num_running(job_ids).zero? end + # Returns true if the given job is running + # + # job_id - The Sidekiq job ID to check. + def self.running?(job_id) + num_running([job_id]) > 0 + end + # Returns the number of jobs that are running. # # job_ids - The Sidekiq job IDs to check. diff --git a/spec/lib/gitlab/sidekiq_status_spec.rb b/spec/lib/gitlab/sidekiq_status_spec.rb index c2e77ef6b6c..884f27b212c 100644 --- a/spec/lib/gitlab/sidekiq_status_spec.rb +++ b/spec/lib/gitlab/sidekiq_status_spec.rb @@ -39,6 +39,18 @@ describe Gitlab::SidekiqStatus do end end + describe '.running?', :clean_gitlab_redis_shared_state do + it 'returns true if job is running' do + described_class.set('123') + + expect(described_class.running?('123')).to be(true) + end + + it 'returns false if job is not found' do + expect(described_class.running?('123')).to be(false) + end + end + describe '.num_running', :clean_gitlab_redis_shared_state do it 'returns 0 if all jobs have been completed' do expect(described_class.num_running(%w(123))).to eq(0) diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 950af653c80..8045cadefe5 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1472,11 +1472,31 @@ describe MergeRequest do end describe '#merge_ongoing?' do - it 'returns true when merge_id is present and MR is not merged' do + it 'returns true when merge_id, MR is not merged and it has no running job' do merge_request = build_stubbed(:merge_request, state: :open, merge_jid: 'foo') + allow(Gitlab::SidekiqStatus).to receive(:running?).with('foo') { true } expect(merge_request.merge_ongoing?).to be(true) end + + it 'returns false when merge_jid is nil' do + merge_request = build_stubbed(:merge_request, state: :open, merge_jid: nil) + + expect(merge_request.merge_ongoing?).to be(false) + end + + it 'returns false if MR is merged' do + merge_request = build_stubbed(:merge_request, state: :merged, merge_jid: 'foo') + + expect(merge_request.merge_ongoing?).to be(false) + end + + it 'returns false if there is no merge job running' do + merge_request = build_stubbed(:merge_request, state: :open, merge_jid: 'foo') + allow(Gitlab::SidekiqStatus).to receive(:running?).with('foo') { false } + + expect(merge_request.merge_ongoing?).to be(false) + end end describe "#closed_without_fork?" do -- GitLab From 12b99260c7be0e4c0441f5722da8a96764b5ada3 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 12 Oct 2017 14:39:51 +0000 Subject: [PATCH 013/149] Merge branch '37691-subscription-fires-multiple-notifications' into 'master' fix multiple notifications from being sent for multiple labels Closes #37691 See merge request gitlab-org/gitlab-ce!14798 --- app/services/notification_service.rb | 2 +- ...1-subscription-fires-multiple-notifications.yml | 5 +++++ spec/services/notification_service_spec.rb | 12 ++++++++++++ spec/support/email_helpers.rb | 14 +++++++------- 4 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 changelogs/unreleased/37691-subscription-fires-multiple-notifications.yml diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 8d5da459882..be3b4b2ba07 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -390,7 +390,7 @@ class NotificationService end def relabeled_resource_email(target, labels, current_user, method) - recipients = labels.flat_map { |l| l.subscribers(target.project) } + recipients = labels.flat_map { |l| l.subscribers(target.project) }.uniq recipients = notifiable_users( recipients, :subscription, target: target, diff --git a/changelogs/unreleased/37691-subscription-fires-multiple-notifications.yml b/changelogs/unreleased/37691-subscription-fires-multiple-notifications.yml new file mode 100644 index 00000000000..c3c38b35fa7 --- /dev/null +++ b/changelogs/unreleased/37691-subscription-fires-multiple-notifications.yml @@ -0,0 +1,5 @@ +--- +title: Fixed duplicate notifications when added multiple labels on an issue +merge_request: 14798 +author: +type: fixed diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index b64ca5be8fc..b13e12e7c94 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -731,6 +731,18 @@ describe NotificationService, :mailer do should_not_email(@u_participating) end + it "doesn't send multiple email when a user is subscribed to multiple given labels" do + subscriber_to_both = create(:user) do |user| + [label_1, label_2].each { |label| label.toggle_subscription(user, project) } + end + + notification.relabeled_issue(issue, [label_1, label_2], @u_disabled) + + should_email(subscriber_to_label_1) + should_email(subscriber_to_label_2) + should_email(subscriber_to_both) + end + context 'confidential issues' do let(:author) { create(:user) } let(:assignee) { create(:user) } diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb index 3e979f2f470..b39052923dd 100644 --- a/spec/support/email_helpers.rb +++ b/spec/support/email_helpers.rb @@ -1,6 +1,6 @@ module EmailHelpers - def sent_to_user?(user, recipients = email_recipients) - recipients.include?(user.notification_email) + def sent_to_user(user, recipients: email_recipients) + recipients.count { |to| to == user.notification_email } end def reset_delivered_emails! @@ -10,17 +10,17 @@ module EmailHelpers def should_only_email(*users, kind: :to) recipients = email_recipients(kind: kind) - users.each { |user| should_email(user, recipients) } + users.each { |user| should_email(user, recipients: recipients) } expect(recipients.count).to eq(users.count) end - def should_email(user, recipients = email_recipients) - expect(sent_to_user?(user, recipients)).to be_truthy + def should_email(user, times: 1, recipients: email_recipients) + expect(sent_to_user(user, recipients: recipients)).to eq(times) end - def should_not_email(user, recipients = email_recipients) - expect(sent_to_user?(user, recipients)).to be_falsey + def should_not_email(user, recipients: email_recipients) + should_email(user, times: 0, recipients: recipients) end def should_not_email_anyone -- GitLab From edd44f155bb6e1307ec8f3b38c60b53b8dedd3da Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 10 Oct 2017 12:48:19 +0000 Subject: [PATCH 014/149] Merge branch '38245-private-avatars-are-not-cdn-compatible' into 'master' Resolve "Private Avatars are not CDN compatible" Closes #38245 and gitlab-com/support-forum#2476 See merge request gitlab-org/gitlab-ce!14443 --- app/helpers/groups_helper.rb | 9 +++- app/helpers/lazy_image_tag_helper.rb | 1 + app/models/concerns/avatarable.rb | 2 +- app/serializers/group_entity.rb | 2 +- app/views/admin/groups/_group.html.haml | 2 +- app/views/admin/groups/show.html.haml | 2 +- app/views/groups/_home_panel.html.haml | 2 +- app/views/groups/edit.html.haml | 2 +- .../layouts/nav/sidebar/_group.html.haml | 2 +- app/views/shared/groups/_group.html.haml | 2 +- app/views/shared/members/_group.html.haml | 2 +- app/views/users/_groups.html.haml | 2 +- spec/helpers/application_helper_spec.rb | 8 ++-- spec/helpers/groups_helper_spec.rb | 45 ++++++++++++++++++- spec/models/project_spec.rb | 2 +- 15 files changed, 67 insertions(+), 18 deletions(-) diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index 82bceddf1f0..676c1d1988b 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -7,7 +7,12 @@ module GroupsHelper can?(current_user, :change_share_with_group_lock, group) end - def group_icon(group) + def group_icon(group, options = {}) + img_path = group_icon_url(group, options) + image_tag img_path, options + end + + def group_icon_url(group, options = {}) if group.is_a?(String) group = Group.find_by_full_path(group) end @@ -89,7 +94,7 @@ module GroupsHelper link_to(group_path(group), class: "group-path #{'breadcrumb-item-text' unless for_dropdown} js-breadcrumb-item-text #{'hidable' if hidable}") do output = if (group.try(:avatar_url) || show_avatar) && !Rails.env.test? - image_tag(group_icon(group), class: "avatar-tile", width: 15, height: 15) + group_icon(group, class: "avatar-tile", width: 15, height: 15) else "" end diff --git a/app/helpers/lazy_image_tag_helper.rb b/app/helpers/lazy_image_tag_helper.rb index 2c5619ac41b..603b9438e35 100644 --- a/app/helpers/lazy_image_tag_helper.rb +++ b/app/helpers/lazy_image_tag_helper.rb @@ -10,6 +10,7 @@ module LazyImageTagHelper unless options.delete(:lazy) == false options[:data] ||= {} options[:data][:src] = path_to_image(source) + options[:class] ||= "" options[:class] << " lazy" diff --git a/app/models/concerns/avatarable.rb b/app/models/concerns/avatarable.rb index 8fbfed11bdf..2ec70203710 100644 --- a/app/models/concerns/avatarable.rb +++ b/app/models/concerns/avatarable.rb @@ -11,7 +11,7 @@ module Avatarable # If asset_host is set then it is expected that assets are handled by a standalone host. # That means we do not want to get GitLab's relative_url_root option anymore. - host = asset_host.present? ? asset_host : gitlab_host + host = (asset_host.present? && (!respond_to?(:public?) || public?)) ? asset_host : gitlab_host [host, avatar.url].join end diff --git a/app/serializers/group_entity.rb b/app/serializers/group_entity.rb index 7c872a3e986..6d8466da902 100644 --- a/app/serializers/group_entity.rb +++ b/app/serializers/group_entity.rb @@ -45,6 +45,6 @@ class GroupEntity < Grape::Entity end expose :avatar_url do |group| - group_icon(group) + group_icon_url(group) end end diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml index e3a77dfdf10..47cc2d4d27e 100644 --- a/app/views/admin/groups/_group.html.haml +++ b/app/views/admin/groups/_group.html.haml @@ -20,7 +20,7 @@ = visibility_level_icon(group.visibility_level, fw: false) .avatar-container.s40 - = image_tag group_icon(group), class: "avatar s40 hidden-xs" + = group_icon(group, class: "avatar s40 hidden-xs") .title = link_to [:admin, group], class: 'group-name' do = group.full_name diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 3e02f7b1e16..2545cecc721 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -16,7 +16,7 @@ %ul.well-list %li .avatar-container.s60 - = image_tag group_icon(@group), class: "avatar s60" + = group_icon(@group, class: "avatar s60") %li %span.light Name: %strong= @group.name diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml index 181c7bee702..a0760c2073b 100644 --- a/app/views/groups/_home_panel.html.haml +++ b/app/views/groups/_home_panel.html.haml @@ -1,7 +1,7 @@ .group-home-panel.text-center %div{ class: container_class } .avatar-container.s70.group-avatar - = image_tag group_icon(@group), class: "avatar s70 avatar-tile" + = group_icon(@group, class: "avatar s70 avatar-tile") %h1.group-title = @group.name %span.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) } diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index 15606dd30fd..16038ef2f79 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -10,7 +10,7 @@ .form-group .col-sm-offset-2.col-sm-10 .avatar-container.s160 - = image_tag group_icon(@group), alt: '', class: 'avatar group-avatar s160' + = group_icon(@group, alt: '', class: 'avatar group-avatar s160') %p.light - if @group.avatar? You can change your group avatar here diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml index 8cba495f7e4..0bf318b0b66 100644 --- a/app/views/layouts/nav/sidebar/_group.html.haml +++ b/app/views/layouts/nav/sidebar/_group.html.haml @@ -6,7 +6,7 @@ .context-header = link_to group_path(@group), title: @group.name do .avatar-container.s40.group-avatar - = image_tag group_icon(@group), class: "avatar s40 avatar-tile" + = group_icon(@group, class: "avatar s40 avatar-tile") .sidebar-context-title = @group.name %ul.sidebar-top-level-items diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml index b361ec86ced..63f62eb476e 100644 --- a/app/views/shared/groups/_group.html.haml +++ b/app/views/shared/groups/_group.html.haml @@ -28,7 +28,7 @@ .avatar-container.s40 = link_to group do - = image_tag group_icon(group), class: "avatar s40 hidden-xs" + = group_icon(group, class: "avatar s40 hidden-xs") .title = link_to group_name, group, class: 'group-name' diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml index bcdad3c153a..5868c52566d 100644 --- a/app/views/shared/members/_group.html.haml +++ b/app/views/shared/members/_group.html.haml @@ -4,7 +4,7 @@ - dom_id = "group_member_#{group_link.id}" %li.member.group_member{ id: dom_id } %span.list-item-name - = image_tag group_icon(group), class: "avatar s40", alt: '' + = group_icon(group, class: "avatar s40", alt: '') %strong = link_to group.full_name, group_path(group) .cgray diff --git a/app/views/users/_groups.html.haml b/app/views/users/_groups.html.haml index eff6c80d144..55799e10a46 100644 --- a/app/views/users/_groups.html.haml +++ b/app/views/users/_groups.html.haml @@ -2,4 +2,4 @@ - groups.each do |group| = link_to group, class: 'profile-groups-avatars inline', title: group.name do .avatar-container.s40 - = image_tag group_icon(group), class: 'avatar group-avatar s40' + = group_icon(group, class: 'avatar group-avatar s40') diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 10bc5f2ecd2..87ae1fa5660 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -57,15 +57,17 @@ describe ApplicationHelper do end describe 'project_icon' do + let(:asset_host) { 'http://assets' } + it 'returns an url for the avatar' do - project = create(:project, avatar: File.open(uploaded_image_temp_path)) + project = create(:project, :public, avatar: File.open(uploaded_image_temp_path)) avatar_url = "/uploads/-/system/project/avatar/#{project.id}/banana_sample.gif" expect(helper.project_icon(project.full_path).to_s) .to eq "" - allow(ActionController::Base).to receive(:asset_host).and_return(gitlab_host) - avatar_url = "#{gitlab_host}/uploads/-/system/project/avatar/#{project.id}/banana_sample.gif" + allow(ActionController::Base).to receive(:asset_host).and_return(asset_host) + avatar_url = "#{asset_host}/uploads/-/system/project/avatar/#{project.id}/banana_sample.gif" expect(helper.project_icon(project.full_path).to_s) .to eq "" diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb index 76e5964ccf7..97f0ed4904e 100644 --- a/spec/helpers/groups_helper_spec.rb +++ b/spec/helpers/groups_helper_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' describe GroupsHelper do include ApplicationHelper + let(:asset_host) { 'http://assets' } + describe 'group_icon' do avatar_file_path = File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif') @@ -10,14 +12,53 @@ describe GroupsHelper do group = create(:group) group.avatar = fixture_file_upload(avatar_file_path) group.save! - expect(group_icon(group.path).to_s) + + avatar_url = "/uploads/-/system/group/avatar/#{group.id}/banana_sample.gif" + + expect(helper.group_icon(group).to_s) + .to eq "" + + allow(ActionController::Base).to receive(:asset_host).and_return(asset_host) + avatar_url = "#{asset_host}/uploads/-/system/group/avatar/#{group.id}/banana_sample.gif" + + expect(helper.group_icon(group).to_s) + .to eq "" + end + end + + describe 'group_icon_url' do + avatar_file_path = File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif') + + it 'returns an url for the avatar' do + group = create(:group) + group.avatar = fixture_file_upload(avatar_file_path) + group.save! + expect(group_icon_url(group.path).to_s) + .to match("/uploads/-/system/group/avatar/#{group.id}/banana_sample.gif") + end + + it 'returns an CDN url for the avatar' do + allow(ActionController::Base).to receive(:asset_host).and_return(asset_host) + group = create(:group) + group.avatar = fixture_file_upload(avatar_file_path) + group.save! + expect(group_icon_url(group.path).to_s) + .to match("#{asset_host}/uploads/-/system/group/avatar/#{group.id}/banana_sample.gif") + end + + it 'returns an based url for the avatar if private' do + allow(ActionController::Base).to receive(:asset_host).and_return(asset_host) + group = create(:group, :private) + group.avatar = fixture_file_upload(avatar_file_path) + group.save! + expect(group_icon_url(group.path).to_s) .to match("/uploads/-/system/group/avatar/#{group.id}/banana_sample.gif") end it 'gives default avatar_icon when no avatar is present' do group = create(:group) group.save! - expect(group_icon(group.path)).to match_asset_path('group_avatar.png') + expect(group_icon_url(group.path)).to match_asset_path('group_avatar.png') end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index a26c71e5155..cf26dbfea49 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -874,7 +874,7 @@ describe Project do let(:project) { create(:project) } context 'when avatar file is uploaded' do - let(:project) { create(:project, :with_avatar) } + let(:project) { create(:project, :public, :with_avatar) } let(:avatar_path) { "/uploads/-/system/project/avatar/#{project.id}/dk.png" } let(:gitlab_host) { "http://#{Gitlab.config.gitlab.host}" } -- GitLab From e4b180f236295536342c694fb4a7aaa0b8a3faaf Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 13 Oct 2017 11:58:53 +0000 Subject: [PATCH 015/149] Merge branch 'backport-ee-2869' into 'master' backport for gitlab-ee!2869 See merge request gitlab-org/gitlab-ce!14505 --- .../components/sidebar/_labels.html.haml | 2 +- spec/features/boards/sidebar_spec.rb | 32 ++++++++++--------- spec/support/board_helpers.rb | 16 ++++++++++ 3 files changed, 34 insertions(+), 16 deletions(-) create mode 100644 spec/support/board_helpers.rb diff --git a/app/views/shared/boards/components/sidebar/_labels.html.haml b/app/views/shared/boards/components/sidebar/_labels.html.haml index 1f540bdaf93..dfc0f9be321 100644 --- a/app/views/shared/boards/components/sidebar/_labels.html.haml +++ b/app/views/shared/boards/components/sidebar/_labels.html.haml @@ -25,7 +25,7 @@ show_any: "true", project_id: @project&.try(:id), labels: labels_filter_path(false), - namespace_path: @project.try(:namespace).try(:full_path), + namespace_path: @namespace_path, project_path: @project.try(:path) }, ":data-issue-update" => "'#{build_issue_link_base}/' + issue.iid + '.json'" } %span.dropdown-toggle-text diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb index c4817eb947b..4965f803883 100644 --- a/spec/features/boards/sidebar_spec.rb +++ b/spec/features/boards/sidebar_spec.rb @@ -1,6 +1,8 @@ require 'rails_helper' describe 'Issue Boards', :js do + include BoardHelpers + let(:user) { create(:user) } let(:user2) { create(:user) } let(:project) { create(:project, :public) } @@ -309,6 +311,21 @@ describe 'Issue Boards', :js do expect(card).to have_selector('.label', count: 1) expect(card).not_to have_content(stretch.title) end + + it 'creates new label' do + click_card(card) + + page.within('.labels') do + click_link 'Edit' + click_link 'Create new label' + fill_in 'new_label_name', with: 'test label' + first('.suggest-colors-dropdown a').click + click_button 'Create' + wait_for_requests + + expect(page).to have_link 'test label' + end + end end context 'subscription' do @@ -322,19 +339,4 @@ describe 'Issue Boards', :js do end end end - - def click_card(card) - page.within(card) do - first('.card-number').click - end - - wait_for_sidebar - end - - def wait_for_sidebar - # loop until the CSS transition is complete - Timeout.timeout(0.5) do - loop until evaluate_script('$(".right-sidebar").outerWidth()') == 290 - end - end end diff --git a/spec/support/board_helpers.rb b/spec/support/board_helpers.rb new file mode 100644 index 00000000000..507d0432d7f --- /dev/null +++ b/spec/support/board_helpers.rb @@ -0,0 +1,16 @@ +module BoardHelpers + def click_card(card) + within card do + first('.card-number').click + end + + wait_for_sidebar + end + + def wait_for_sidebar + # loop until the CSS transition is complete + Timeout.timeout(0.5) do + loop until evaluate_script('$(".right-sidebar").outerWidth()') == 290 + end + end +end -- GitLab From b21296cd099ed11dc4f237f2cb78531dc4ad316d Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Tue, 10 Oct 2017 17:47:49 +0000 Subject: [PATCH 016/149] Merge branch 'lock-discussion-docs' into 'master' Locked issues / mrs docs Closes #38880 See merge request gitlab-org/gitlab-ce!14770 --- doc/user/discussions/index.md | 38 ++++++++++++++--------------------- doc/user/permissions.md | 2 +- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md index ab46befb91c..23506261f12 100644 --- a/doc/user/discussions/index.md +++ b/doc/user/discussions/index.md @@ -153,42 +153,34 @@ comments in greater detail. ![Discussion comment](img/discussion_comment.png) -## Locking discussions +## Lock discussions > [Introduced][ce-14531] in GitLab 10.1. -There might be some cases where a discussion is better off if it's locked down. -For example: +For large projects with many contributors, it may be useful to stop discussions +in issues or merge requests in these scenarios: -- Discussions that are several years old and the issue/merge request is closed, - but people continue to try to resurrect the discussion. -- Discussions where someone or a group of people are trolling, are abusive, or - in-general are causing the discussion to be unproductive. +- The project maintainer has already resolved the discussion and it is not helpful +for continued feedback. The project maintainer has already directed new conversation +to newer issues or merge requests. +- The people participating in the discussion are trolling, abusive, or otherwise +being unproductive. -In locked discussions, only team members can write new comments and edit the old -ones. +In these cases, a user with Master permissions or higher in the project can lock (and unlock) +an issue or a merge request, using the "Lock" section in the sidebar: -To lock or unlock a discussion, you need to have at least Master [permissions]: - -1. Find the "Lock" section in the sidebar and click **Edit** -1. In the dialog that will appear, you can choose to turn on or turn off the - discussion lock -1. Optionally, leave a comment to explain your reasoning behind that action - -| Turn off discussion lock | Turn on discussion lock | +| Unlock | Lock | | :-----------: | :----------: | | ![Turn off discussion lock](img/turn_off_lock.png) | ![Turn on discussion lock](img/turn_on_lock.png) | -Every change is indicated by a system note in the issue's or merge request's -comments. +System notes indicate locking and unlocking. ![Discussion lock system notes](img/discussion_lock_system_notes.png) -Once an issue or merge request is locked, project members can see the indicator -in the comment area, whereas non project members can only see the information -that the discussion is locked. +In a locked issue or merge request, only team members can add new comments and +edit existing comments. Non-team members are restricted from adding or editing comments. -| Team member | Not a member | +| Team member | Non-team member | | :-----------: | :----------: | | ![Comment form member](img/lock_form_member.png) | ![Comment form non-member](img/lock_form_non_member.png) | diff --git a/doc/user/permissions.md b/doc/user/permissions.md index 6e1479ead2d..8b6ff0fe46c 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -25,7 +25,7 @@ The following table depicts the various user permission levels in a project. | Create confidential issue | ✓ [^1] | ✓ | ✓ | ✓ | ✓ | | View confidential issues | (✓) [^2] | ✓ | ✓ | ✓ | ✓ | | Leave comments | ✓ [^1] | ✓ | ✓ | ✓ | ✓ | -| Lock comments | | | | ✓ | ✓ | +| Lock discussions (issues and merge requests) | | | | ✓ | ✓ | | See a list of jobs | ✓ [^3] | ✓ | ✓ | ✓ | ✓ | | See a job log | ✓ [^3] | ✓ | ✓ | ✓ | ✓ | | Download and browse job artifacts | ✓ [^3] | ✓ | ✓ | ✓ | ✓ | -- GitLab From b7f3eac590783eaca40403060cebb459e64cdcb9 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 11 Oct 2017 06:07:55 +0000 Subject: [PATCH 017/149] Merge branch 'docs-image-discussion' into 'master' Add image discussion docs Closes #38879 See merge request gitlab-org/gitlab-ce!14743 --- .../img/image_resolved_discussion.png | Bin 0 -> 48234 bytes doc/user/discussions/img/onion_skin_view.png | Bin 0 -> 45053 bytes .../img/start_image_discussion.gif | Bin 0 -> 146627 bytes doc/user/discussions/img/swipe_view.png | Bin 0 -> 16483 bytes doc/user/discussions/img/two_up_view.png | Bin 0 -> 61759 bytes doc/user/discussions/index.md | 43 ++++++++++++++++-- 6 files changed, 40 insertions(+), 3 deletions(-) create mode 100755 doc/user/discussions/img/image_resolved_discussion.png create mode 100755 doc/user/discussions/img/onion_skin_view.png create mode 100644 doc/user/discussions/img/start_image_discussion.gif create mode 100755 doc/user/discussions/img/swipe_view.png create mode 100755 doc/user/discussions/img/two_up_view.png diff --git a/doc/user/discussions/img/image_resolved_discussion.png b/doc/user/discussions/img/image_resolved_discussion.png new file mode 100755 index 0000000000000000000000000000000000000000..ed00b5c77fe184ec4a39109dffa020ee87ed702a GIT binary patch literal 48234 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 literal 0 HcmV?d00001 diff --git a/doc/user/discussions/img/start_image_discussion.gif b/doc/user/discussions/img/start_image_discussion.gif new file mode 100644 index 0000000000000000000000000000000000000000..43efbf2fbb2502e38fd47cfff2e7f79f15dda1b7 GIT binary patch literal 146627 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 literal 0 HcmV?d00001 diff --git a/doc/user/discussions/img/swipe_view.png b/doc/user/discussions/img/swipe_view.png new file mode 100755 index 0000000000000000000000000000000000000000..82d6e52173cc829e4bda4ca1b638f281d1e980c1 GIT binary patch literal 16483 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 ZuVXy(#BKlfJrCMJ5}vMpF6*2UngHuhoCE*> literal 0 HcmV?d00001 diff --git a/doc/user/discussions/img/two_up_view.png b/doc/user/discussions/img/two_up_view.png new file mode 100755 index 0000000000000000000000000000000000000000..d9e90708e873f211420ff497aa8b0c7f76f30548 GIT binary patch literal 61759 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%0DtIsfJp0drr>T*31+J!t***Bis_LzX|-TLP`= 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 [Introduced][ce-14531] in GitLab 10.1. + +Sometimes a discussion is revolved around an image. With image discussions, +you can easily target a specific coordinate of an image and start a discussion +around it. Image discussions are available in merge requests and commit detail views. + +To start an image discussion, hover your mouse over the image. Your mouse pointer +should convert into an icon, indicating that the image is available for commenting. +Simply click anywhere on the image to create a new discussion. + +![Start image discussion](img/start_image_discussion.gif) + +After you click on the image, a comment form will be displayed that would be the start +of your discussion. Once you save your comment, you will see a new badge displayed on +top of your image. This badge represents your discussion. + +>**Note:** +This discussion badge is typically associated with a number that is only used as a visual +reference for each discussion. In the merge request discussion tab, +this badge will be indicated with a comment icon since each discussion will render a new +image section. + +Image discussions also work on diffs that replace an existing image. In this diff view +mode, you can toggle the different view modes and still see the discussion point badges. + +| 2-up | Swipe | Onion Skin | +| :-----------: | :----------: | :----------: | +| ![2-up view](img/two_up_view.png) | ![swipe view](img/swipe_view.png) | ![onion skin view](img/onion_skin_view.png) | + +Image discussions also work well with resolvable discussions. Resolved discussions +on diffs (not on the merge request discussion tab) will appear collapsed on page +load and will have a corresponding badge counter to match the counter on the image. + +![Image resolved discussion](img/image_resolved_discussion.png) + ## Lock discussions > [Introduced][ce-14531] in GitLab 10.1. @@ -163,8 +200,8 @@ in issues or merge requests in these scenarios: - The project maintainer has already resolved the discussion and it is not helpful for continued feedback. The project maintainer has already directed new conversation to newer issues or merge requests. -- The people participating in the discussion are trolling, abusive, or otherwise -being unproductive. +- The people participating in the discussion are trolling, abusive, or otherwise +being unproductive. In these cases, a user with Master permissions or higher in the project can lock (and unlock) an issue or a merge request, using the "Lock" section in the sidebar: @@ -177,7 +214,7 @@ System notes indicate locking and unlocking. ![Discussion lock system notes](img/discussion_lock_system_notes.png) -In a locked issue or merge request, only team members can add new comments and +In a locked issue or merge request, only team members can add new comments and edit existing comments. Non-team members are restricted from adding or editing comments. | Team member | Non-team member | -- GitLab From 161a9eaf6a99382cca34a9c7a7b851a7f74690d4 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 9 Oct 2017 16:55:14 +0000 Subject: [PATCH 018/149] Merge branch 'wiki-empty-page-heading' into 'master' Fix wiki empty page translation namespace not being removed Closes #38920 See merge request gitlab-org/gitlab-ce!14759 --- app/views/projects/wikis/empty.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/wikis/empty.html.haml b/app/views/projects/wikis/empty.html.haml index 911e1339541..d6e568bac94 100644 --- a/app/views/projects/wikis/empty.html.haml +++ b/app/views/projects/wikis/empty.html.haml @@ -1,6 +1,6 @@ - page_title _("Wiki") -%h3.page-title= _("Wiki|Empty page") +%h3.page-title= s_("Wiki|Empty page") %hr .error_message = s_("WikiEmptyPageError|You are not allowed to create wiki pages") -- GitLab From d9088c147f86d40eff0cddb51bcb7dad8c522aee Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Tue, 10 Oct 2017 07:48:36 +0000 Subject: [PATCH 019/149] Merge branch '38574-superfluous-export-in-advanced-settings-of-project-settings' into 'master' Resolve "Superfluous "Export" in "Advanced settings" of project settings" Closes #38574 See merge request gitlab-org/gitlab-ce!14773 --- app/views/projects/edit.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 8ae4fd94146..893e536e289 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -97,7 +97,7 @@ %button.btn.js-settings-toggle = expanded ? 'Collapse' : 'Expand' %p - Perform advanced options such as housekeeping, exporting, archiving, renaming, transferring, or removing your project. + Perform advanced options such as housekeeping, archiving, renaming, transferring, or removing your project. .settings-content.no-animate{ class: ('expanded' if expanded) } .sub-section %h4 Housekeeping -- GitLab From 946635c262ecc0b3cc16c858ca24f60ff3fbc357 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Tue, 10 Oct 2017 12:48:03 +0000 Subject: [PATCH 020/149] Merge branch '38941-lock-note-fix' into 'master' Fix text for the merge request lock system note Closes #38941 See merge request gitlab-org/gitlab-ce!14779 --- app/services/system_note_service.rb | 2 +- .../merge_requests/update_service_spec.rb | 4 +- spec/services/system_note_service_spec.rb | 38 +++++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index 7b32e215c7f..a52dce6cb4b 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -593,7 +593,7 @@ module SystemNoteService def discussion_lock(issuable, author) action = issuable.discussion_locked? ? 'locked' : 'unlocked' - body = "#{action} this issue" + body = "#{action} this #{issuable.class.to_s.titleize.downcase}" create_note(NoteSummary.new(issuable, issuable.project, author, body, action: action)) end diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index b11a1b31f32..3bb694ceac8 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -126,10 +126,10 @@ describe MergeRequests::UpdateService, :mailer do end it 'creates system note about discussion lock' do - note = find_note('locked this issue') + note = find_note('locked this merge request') expect(note).not_to be_nil - expect(note.note).to eq 'locked this issue' + expect(note.note).to eq 'locked this merge request' end context 'when not including source branch removal options' do diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index b1241cd8d0b..cd473c1f388 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -1145,4 +1145,42 @@ describe SystemNoteService do it { expect(subject.note).to eq "marked #{duplicate_issue.to_reference(project)} as a duplicate of this issue" } end end + + describe '.discussion_lock' do + subject { described_class.discussion_lock(noteable, author) } + + context 'discussion unlocked' do + it_behaves_like 'a system note' do + let(:action) { 'unlocked' } + end + + it 'creates the note text correctly' do + [:issue, :merge_request].each do |type| + issuable = create(type) + + expect(described_class.discussion_lock(issuable, author).note) + .to eq("unlocked this #{type.to_s.titleize.downcase}") + end + end + end + + context 'discussion locked' do + before do + noteable.update_attribute(:discussion_locked, true) + end + + it_behaves_like 'a system note' do + let(:action) { 'locked' } + end + + it 'creates the note text correctly' do + [:issue, :merge_request].each do |type| + issuable = create(type, discussion_locked: true) + + expect(described_class.discussion_lock(issuable, author).note) + .to eq("locked this #{type.to_s.titleize.downcase}") + end + end + end + end end -- GitLab From c88e4979aa247028f3de41ba27fe1848e3e90ddd Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 10 Oct 2017 20:41:52 +0000 Subject: [PATCH 021/149] Merge branch 'add-resolve-discussion-test' into 'master' Add explicit test to test resolved discussion toggle content See merge request gitlab-org/gitlab-ce!14796 --- .../merge_requests/diff_notes_resolve_spec.rb | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/spec/features/merge_requests/diff_notes_resolve_spec.rb b/spec/features/merge_requests/diff_notes_resolve_spec.rb index 637e6036384..475c8586f45 100644 --- a/spec/features/merge_requests/diff_notes_resolve_spec.rb +++ b/spec/features/merge_requests/diff_notes_resolve_spec.rb @@ -88,14 +88,24 @@ feature 'Diff notes resolve', :js do end end - it 'hides resolved discussion' do - page.within '.diff-content' do - click_button 'Resolve discussion' + describe 'resolved discussion' do + before do + page.within '.diff-content' do + click_button 'Resolve discussion' + end + + visit_merge_request end - visit_merge_request + it 'hides when resolve discussion is clicked' do + expect(page).to have_selector('.discussion-body', visible: false) + end - expect(page).to have_selector('.discussion-body', visible: false) + it 'shows resolved discussion when toggled' do + find(".timeline-content .discussion[data-discussion-id='#{note.discussion_id}'] .discussion-toggle-button").click + + expect(page.find(".timeline-content #note_#{note.noteable_id}")).to be_visible + end end it 'allows user to resolve from reply form without a comment' do -- GitLab From 14690f2b3898c4849f68c46a46a2511078f8a31c Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Wed, 11 Oct 2017 09:00:49 +0000 Subject: [PATCH 022/149] Merge branch 'milestones-permissions-docs' into 'master' Developer can create/edit/delete milestones See merge request gitlab-org/gitlab-ce!14797 --- doc/user/permissions.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/user/permissions.md b/doc/user/permissions.md index 8b6ff0fe46c..c03700a3501 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -54,7 +54,7 @@ The following table depicts the various user permission levels in a project. | Create or update commit status | | | ✓ | ✓ | ✓ | | Update a container registry | | | ✓ | ✓ | ✓ | | Remove a container registry image | | | ✓ | ✓ | ✓ | -| Create new milestones | | | | ✓ | ✓ | +| Create/edit/delete project milestones | | | ✓ | ✓ | ✓ | | Add new team members | | | | ✓ | ✓ | | Push to protected branches | | | | ✓ | ✓ | | Enable/disable branch protection | | | | ✓ | ✓ | @@ -144,6 +144,7 @@ group. | Manage group members | | | | | ✓ | | Remove group | | | | | ✓ | | Manage group labels | | ✓ | ✓ | ✓ | ✓ | +| Create/edit/delete group milestones | | | ✓ | ✓ | ✓ | ### Subgroup permissions -- GitLab From 45ca71b09c30b42179354c323bba18a552eba83f Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Fri, 13 Oct 2017 07:13:39 +0000 Subject: [PATCH 023/149] Merge branch 'fix-cursor-path' into 'master' Use image-url instead of url so that asset pipeline can do it's thing Closes #38980 See merge request gitlab-org/gitlab-ce!14799 --- app/assets/stylesheets/pages/diff.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index ffb5fc94475..09f831dcb29 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -707,11 +707,11 @@ .frame.click-to-comment { position: relative; - cursor: url(icon_image_comment.svg) + cursor: image-url('icon_image_comment.svg') $image-comment-cursor-left-offset $image-comment-cursor-top-offset, auto; // Retina cursor - cursor: -webkit-image-set(url(icon_image_comment.svg) 1x, url(icon_image_comment@2x.svg) 2x) + cursor: -webkit-image-set(image-url('icon_image_comment.svg') 1x, image-url('icon_image_comment@2x.svg') 2x) $image-comment-cursor-left-offset $image-comment-cursor-top-offset, auto; .comment-indicator { -- GitLab From cc411c7145f07cb68c33b3576ec9bd3031626ceb Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 11 Oct 2017 14:35:23 +0000 Subject: [PATCH 024/149] Merge branch 'docs-patch-28' into 'master' Update image commenting MR link in docs See merge request gitlab-org/gitlab-ce!14816 --- doc/user/discussions/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md index 5bd326a426f..2206b2860f4 100644 --- a/doc/user/discussions/index.md +++ b/doc/user/discussions/index.md @@ -155,7 +155,7 @@ comments in greater detail. ## Image discussions -> [Introduced][ce-14531] in GitLab 10.1. +> [Introduced][ce-14061] in GitLab 10.1. Sometimes a discussion is revolved around an image. With image discussions, you can easily target a specific coordinate of an image and start a discussion @@ -227,6 +227,7 @@ edit existing comments. Non-team members are restricted from adding or editing c [ce-7180]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7180 [ce-8266]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8266 [ce-14053]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14053 +[ce-14061]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14061 [ce-14531]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14531 [resolve-discussion-button]: img/resolve_discussion_button.png [resolve-comment-button]: img/resolve_comment_button.png -- GitLab From 3a78e96e55b3428d7faa80edf140f3bd87566f74 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 12 Oct 2017 13:48:31 +0000 Subject: [PATCH 025/149] Merge branch 'cache-issuable-template-names' into 'master' Cache issuable template names See merge request gitlab-org/gitlab-ce!14823 --- app/helpers/issuables_helper.rb | 12 ++------ app/models/blob.rb | 4 ++- app/models/repository.rb | 17 +++++++++-- .../cache-issuable-template-names.yml | 5 ++++ lib/gitlab/file_detector.rb | 28 +++++++++---------- spec/lib/gitlab/file_detector_spec.rb | 12 ++++++++ spec/models/repository_spec.rb | 4 ++- 7 files changed, 54 insertions(+), 28 deletions(-) create mode 100644 changelogs/unreleased/cache-issuable-template-names.yml diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 7713fb0b9f8..baa2d6e375e 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -314,20 +314,12 @@ module IssuablesHelper @issuable_templates ||= case issuable when Issue - issue_template_names + ref_project.repository.issue_template_names when MergeRequest - merge_request_template_names + ref_project.repository.merge_request_template_names end end - def merge_request_template_names - @merge_request_templates ||= Gitlab::Template::MergeRequestTemplate.dropdown_names(ref_project) - end - - def issue_template_names - @issue_templates ||= Gitlab::Template::IssueTemplate.dropdown_names(ref_project) - end - def selected_template(issuable) params[:issuable_template] if issuable_templates(issuable).any? { |template| template[:name] == params[:issuable_template] } end diff --git a/app/models/blob.rb b/app/models/blob.rb index 954d4e4d779..ad0bc2e2ead 100644 --- a/app/models/blob.rb +++ b/app/models/blob.rb @@ -156,7 +156,9 @@ class Blob < SimpleDelegator end def file_type - Gitlab::FileDetector.type_of(path) + name = File.basename(path) + + Gitlab::FileDetector.type_of(path) || Gitlab::FileDetector.type_of(name) end def video? diff --git a/app/models/repository.rb b/app/models/repository.rb index d725c65081d..bf526ca1762 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -34,7 +34,8 @@ class Repository CACHED_METHODS = %i(size commit_count rendered_readme contribution_guide changelog license_blob license_key gitignore koding_yml gitlab_ci_yml branch_names tag_names branch_count - tag_count avatar exists? empty? root_ref has_visible_content?).freeze + tag_count avatar exists? empty? root_ref has_visible_content? + issue_template_names merge_request_template_names).freeze # Methods that use cache_method but only memoize the value MEMOIZED_CACHED_METHODS = %i(license empty_repo?).freeze @@ -50,7 +51,9 @@ class Repository gitignore: :gitignore, koding: :koding_yml, gitlab_ci: :gitlab_ci_yml, - avatar: :avatar + avatar: :avatar, + issue_template: :issue_template_names, + merge_request_template: :merge_request_template_names }.freeze # Wraps around the given method and caches its output in Redis and an instance @@ -535,6 +538,16 @@ class Repository end cache_method :avatar + def issue_template_names + Gitlab::Template::IssueTemplate.dropdown_names(project) + end + cache_method :issue_template_names, fallback: [] + + def merge_request_template_names + Gitlab::Template::MergeRequestTemplate.dropdown_names(project) + end + cache_method :merge_request_template_names, fallback: [] + def readme if readme = tree(:head)&.readme ReadmeBlob.new(readme, self) diff --git a/changelogs/unreleased/cache-issuable-template-names.yml b/changelogs/unreleased/cache-issuable-template-names.yml new file mode 100644 index 00000000000..858fdff2db2 --- /dev/null +++ b/changelogs/unreleased/cache-issuable-template-names.yml @@ -0,0 +1,5 @@ +--- +title: Cache issue and MR template names in Redis +merge_request: +author: +type: other diff --git a/lib/gitlab/file_detector.rb b/lib/gitlab/file_detector.rb index a8cb7fc3fe7..0e9ef4f897c 100644 --- a/lib/gitlab/file_detector.rb +++ b/lib/gitlab/file_detector.rb @@ -6,31 +6,33 @@ module Gitlab module FileDetector PATTERNS = { # Project files - readme: /\Areadme/i, - changelog: /\A(changelog|history|changes|news)/i, - license: /\A(licen[sc]e|copying)(\..+|\z)/i, - contributing: /\Acontributing/i, + readme: /\Areadme[^\/]*\z/i, + changelog: /\A(changelog|history|changes|news)[^\/]*\z/i, + license: /\A(licen[sc]e|copying)(\.[^\/]+)?\z/i, + contributing: /\Acontributing[^\/]*\z/i, version: 'version', avatar: /\Alogo\.(png|jpg|gif)\z/, + issue_template: /\A\.gitlab\/issue_templates\/[^\/]+\.md\z/, + merge_request_template: /\A\.gitlab\/merge_request_templates\/[^\/]+\.md\z/, # Configuration files gitignore: '.gitignore', koding: '.koding.yml', gitlab_ci: '.gitlab-ci.yml', - route_map: 'route-map.yml', + route_map: '.gitlab/route-map.yml', # Dependency files - cartfile: /\ACartfile/, + cartfile: /\ACartfile[^\/]*\z/, composer_json: 'composer.json', gemfile: /\A(Gemfile|gems\.rb)\z/, gemfile_lock: 'Gemfile.lock', - gemspec: /\.gemspec\z/, + gemspec: /\A[^\/]*\.gemspec\z/, godeps_json: 'Godeps.json', package_json: 'package.json', podfile: 'Podfile', - podspec_json: /\.podspec\.json\z/, - podspec: /\.podspec\z/, - requirements_txt: /requirements\.txt\z/, + podspec_json: /\A[^\/]*\.podspec\.json\z/, + podspec: /\A[^\/]*\.podspec\z/, + requirements_txt: /\A[^\/]*requirements\.txt\z/, yarn_lock: 'yarn.lock' }.freeze @@ -63,13 +65,11 @@ module Gitlab # type_of('README.md') # => :readme # type_of('VERSION') # => :version def self.type_of(path) - name = File.basename(path) - PATTERNS.each do |type, search| did_match = if search.is_a?(Regexp) - name =~ search + path =~ search else - name.casecmp(search) == 0 + path.casecmp(search) == 0 end return type if did_match diff --git a/spec/lib/gitlab/file_detector_spec.rb b/spec/lib/gitlab/file_detector_spec.rb index 695fd6f8573..8e524f9b05a 100644 --- a/spec/lib/gitlab/file_detector_spec.rb +++ b/spec/lib/gitlab/file_detector_spec.rb @@ -18,6 +18,10 @@ describe Gitlab::FileDetector do expect(described_class.type_of('README.md')).to eq(:readme) end + it 'returns nil for a README file in a directory' do + expect(described_class.type_of('foo/README.md')).to be_nil + end + it 'returns the type of a changelog file' do %w(CHANGELOG HISTORY CHANGES NEWS).each do |file| expect(described_class.type_of(file)).to eq(:changelog) @@ -52,6 +56,14 @@ describe Gitlab::FileDetector do end end + it 'returns the type of an issue template' do + expect(described_class.type_of('.gitlab/issue_templates/foo.md')).to eq(:issue_template) + end + + it 'returns the type of a merge request template' do + expect(described_class.type_of('.gitlab/merge_request_templates/foo.md')).to eq(:merge_request_template) + end + it 'returns nil for an unknown file' do expect(described_class.type_of('foo.txt')).to be_nil end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 5d78aed5b4f..f44693a71bb 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1509,7 +1509,9 @@ describe Repository do :gitignore, :koding, :gitlab_ci, - :avatar + :avatar, + :issue_template, + :merge_request_template ]) repository.after_change_head -- GitLab From 7358c69f26a32eb6ba606fe77cb138368aa3474d Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 12 Oct 2017 10:01:47 +0000 Subject: [PATCH 026/149] Merge branch '39001-mr-tabs-hover' into 'master' Fixes from CSS refactor Closes #39001 and #38939 See merge request gitlab-org/gitlab-ce!14828 --- .../stylesheets/framework/secondary-navigation-elements.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/assets/stylesheets/framework/secondary-navigation-elements.scss b/app/assets/stylesheets/framework/secondary-navigation-elements.scss index 5c96b3b78e7..3fd2549b143 100644 --- a/app/assets/stylesheets/framework/secondary-navigation-elements.scss +++ b/app/assets/stylesheets/framework/secondary-navigation-elements.scss @@ -6,6 +6,7 @@ margin: 0; list-style: none; height: auto; + border-bottom: 1px solid $border-color; li { display: flex; @@ -24,6 +25,7 @@ &:focus { text-decoration: none; color: $black; + border-bottom: 2px solid $gray-darkest; .badge { color: $black; -- GitLab From c7b8e61d8db9eca4abb8a2b2fcac0eababa28a09 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 25 Sep 2017 13:33:45 +0000 Subject: [PATCH 027/149] Merge branch 'winh-search-bar-xss' into 'security-10-0' Escape user name in filtered search bar See merge request gitlab/gitlabhq!2194 --- .../filtered_search_visual_tokens.js | 4 ++-- .../filtered_search_visual_tokens_spec.js | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js index 28e8240169d..55c153a6d46 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js +++ b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js @@ -123,8 +123,8 @@ class FilteredSearchVisualTokens { /* eslint-disable no-param-reassign */ tokenValueContainer.dataset.originalValue = tokenValue; tokenValueElement.innerHTML = ` - ${user.name}'s avatar - ${user.name} + + ${_.escape(user.name)} `; /* eslint-enable no-param-reassign */ }) diff --git a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js b/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js index 67166802c70..2ecb64d84b5 100644 --- a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js +++ b/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js @@ -791,6 +791,29 @@ describe('Filtered Search Visual Tokens', () => { expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name); const avatar = tokenValueElement.querySelector('img.avatar'); expect(avatar.src).toBe(dummyUser.avatar_url); + expect(avatar.alt).toBe(''); + }) + .then(done) + .catch(done.fail); + }); + + it('escapes user name when creating token', (done) => { + const dummyUser = { + name: '#{section_end}" + + expect(convert_html(text)).not_to include('' + end + end end context 'editing issue labels', :js do -- GitLab From 1da3b9dce82dec706863dc8d205d6dc365c19f88 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 5 Jan 2018 17:54:29 +0000 Subject: [PATCH 138/149] Merge branch 'milestones-finder-order-fix-10-1' into 'security-10-1' Remove order param from the MilestoneFinder - 10.1 port See merge request gitlab/gitlabhq!2265 (cherry picked from commit 5f0bb7928b40029a2ced18063c36697e3f8e80c2) 85c6530e Remove order param from the MilestoneFinder --- .../groups/milestones_controller.rb | 6 ++- .../projects/milestones_controller.rb | 14 ++++--- app/finders/milestones_finder.rb | 8 +--- app/models/global_milestone.rb | 8 ++-- .../milestones-finder-order-fix.yml | 5 +++ spec/finders/milestones_finder_spec.rb | 41 ++++++------------- .../projects/autocomplete_service_spec.rb | 15 +++---- 7 files changed, 43 insertions(+), 54 deletions(-) create mode 100644 changelogs/unreleased/milestones-finder-order-fix.yml diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 7a7bcb1a3d2..310aeb0f0d6 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -75,8 +75,6 @@ class Groups::MilestonesController < Groups::ApplicationController end def milestones - search_params = params.merge(group_ids: group.id) - milestones = MilestonesFinder.new(search_params).execute legacy_milestones = GroupMilestone.build_collection(group, group_projects, params) @@ -93,4 +91,8 @@ class Groups::MilestonesController < Groups::ApplicationController render_404 unless @milestone end + + def search_params + params.permit(:state).merge(group_ids: group.id) + end end diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index c94384d2a1a..9219a9551df 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -84,12 +84,6 @@ class Projects::MilestonesController < Projects::ApplicationController def milestones @milestones ||= begin - if @project.group && can?(current_user, :read_group, @project.group) - group = @project.group - end - - search_params = params.merge(project_ids: @project.id, group_ids: group&.id) - MilestonesFinder.new(search_params).execute end end @@ -105,4 +99,12 @@ class Projects::MilestonesController < Projects::ApplicationController def milestone_params params.require(:milestone).permit(:title, :description, :start_date, :due_date, :state_event) end + + def search_params + if @project.group && can?(current_user, :read_group, @project.group) + group = @project.group + end + + params.permit(:state).merge(project_ids: @project.id, group_ids: group&.id) + end end diff --git a/app/finders/milestones_finder.rb b/app/finders/milestones_finder.rb index 0a5a0ea2f35..b4605fca193 100644 --- a/app/finders/milestones_finder.rb +++ b/app/finders/milestones_finder.rb @@ -46,11 +46,7 @@ class MilestonesFinder end def order(items) - if params.has_key?(:order) - items.reorder(params[:order]) - else - order_statement = Gitlab::Database.nulls_last_order('due_date', 'ASC') - items.reorder(order_statement) - end + order_statement = Gitlab::Database.nulls_last_order('due_date', 'ASC') + items.reorder(order_statement).order('title ASC') end end diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb index c0864769314..dc2f6817190 100644 --- a/app/models/global_milestone.rb +++ b/app/models/global_milestone.rb @@ -44,10 +44,10 @@ class GlobalMilestone def self.group_milestones_states_count(group) return STATE_COUNT_HASH unless group - params = { group_ids: [group.id], state: 'all', order: nil } + params = { group_ids: [group.id], state: 'all' } relation = MilestonesFinder.new(params).execute - grouped_by_state = relation.group(:state).count + grouped_by_state = relation.reorder(nil).group(:state).count { opened: grouped_by_state['active'] || 0, @@ -60,10 +60,10 @@ class GlobalMilestone def self.legacy_group_milestone_states_count(projects) return STATE_COUNT_HASH unless projects - params = { project_ids: projects.map(&:id), state: 'all', order: nil } + params = { project_ids: projects.map(&:id), state: 'all' } relation = MilestonesFinder.new(params).execute - project_milestones_by_state_and_title = relation.group(:state, :title).count + project_milestones_by_state_and_title = relation.reorder(nil).group(:state, :title).count opened = count_by_state(project_milestones_by_state_and_title, 'active') closed = count_by_state(project_milestones_by_state_and_title, 'closed') diff --git a/changelogs/unreleased/milestones-finder-order-fix.yml b/changelogs/unreleased/milestones-finder-order-fix.yml new file mode 100644 index 00000000000..983c301a82d --- /dev/null +++ b/changelogs/unreleased/milestones-finder-order-fix.yml @@ -0,0 +1,5 @@ +--- +title: Prevent a SQL injection in the MilestonesFinder +merge_request: +author: +type: security diff --git a/spec/finders/milestones_finder_spec.rb b/spec/finders/milestones_finder_spec.rb index 8ae08656e01..0b3cf7ece5f 100644 --- a/spec/finders/milestones_finder_spec.rb +++ b/spec/finders/milestones_finder_spec.rb @@ -21,10 +21,19 @@ describe MilestonesFinder do expect(result).to contain_exactly(milestone_1, milestone_2) end - it 'returns milestones for groups and projects' do - result = described_class.new(project_ids: [project_1.id, project_2.id], group_ids: group.id, state: 'all').execute + context 'milestones for groups and project' do + let(:result) do + described_class.new(project_ids: [project_1.id, project_2.id], group_ids: group.id, state: 'all').execute + end + + it 'returns milestones for groups and projects' do + expect(result).to contain_exactly(milestone_1, milestone_2, milestone_3, milestone_4) + end - expect(result).to contain_exactly(milestone_1, milestone_2, milestone_3, milestone_4) + it 'orders milestones by due date' do + expect(result.first).to eq(milestone_1) + expect(result.second).to eq(milestone_3) + end end context 'with filters' do @@ -61,30 +70,4 @@ describe MilestonesFinder do expect(result.to_a).to contain_exactly(milestone_1) end end - - context 'with order' do - let(:params) do - { - project_ids: [project_1.id, project_2.id], - group_ids: group.id, - state: 'all' - } - end - - it "default orders by due date" do - result = described_class.new(params).execute - - expect(result.first).to eq(milestone_1) - expect(result.second).to eq(milestone_3) - end - - it "orders by parameter" do - result = described_class.new(params.merge(order: 'id DESC')).execute - - expect(result.first).to eq(milestone_4) - expect(result.second).to eq(milestone_3) - expect(result.third).to eq(milestone_2) - expect(result.fourth).to eq(milestone_1) - end - end end diff --git a/spec/services/projects/autocomplete_service_spec.rb b/spec/services/projects/autocomplete_service_spec.rb index 426593be428..b70938b1dbc 100644 --- a/spec/services/projects/autocomplete_service_spec.rb +++ b/spec/services/projects/autocomplete_service_spec.rb @@ -93,26 +93,27 @@ describe Projects::AutocompleteService do let(:user) { create(:user) } let(:group) { create(:group) } let(:project) { create(:project, group: group) } - let!(:group_milestone) { create(:milestone, group: group) } - let!(:project_milestone) { create(:milestone, project: project) } + let!(:group_milestone1) { create(:milestone, group: group, due_date: '2017-01-01', title: 'Second Title') } + let!(:group_milestone2) { create(:milestone, group: group, due_date: '2017-01-01', title: 'First Title') } + let!(:project_milestone) { create(:milestone, project: project, due_date: '2016-01-01') } let(:milestone_titles) { described_class.new(project, user).milestones.map(&:title) } - it 'includes project and group milestones' do - expect(milestone_titles).to eq([group_milestone.title, project_milestone.title]) + it 'includes project and group milestones and sorts them correctly' do + expect(milestone_titles).to eq([project_milestone.title, group_milestone2.title, group_milestone1.title]) end it 'does not include closed milestones' do - group_milestone.close + group_milestone1.close - expect(milestone_titles).to eq([project_milestone.title]) + expect(milestone_titles).to eq([project_milestone.title, group_milestone2.title]) end it 'does not include milestones from other projects in the group' do other_project = create(:project, group: group) project_milestone.update!(project: other_project) - expect(milestone_titles).to eq([group_milestone.title]) + expect(milestone_titles).to eq([group_milestone2.title, group_milestone1.title]) end end end -- GitLab From e151f5d5b59a2c65222e88c4abffbf11a0948cd1 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 3 Jan 2018 23:11:07 +0000 Subject: [PATCH 139/149] Merge branch 'sh-validate-path-project-import-10-1' into 'security-10-1' Validate project path in Gitlab import - 10.1 port See merge request gitlab/gitlabhq!2266 (cherry picked from commit 14e7f46a07a45bf851178ae6c90c519460bf9736) 13ad8b50 Validate project path in Gitlab import --- .../gitlab_projects_import_service.rb | 2 +- .../import/gitlab_projects_controller_spec.rb | 38 +++++++++++++++++++ .../import_export/import_file_spec.rb | 2 +- .../gitlab_projects_import_service_spec.rb | 31 +++++++++++++++ 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 spec/controllers/import/gitlab_projects_controller_spec.rb create mode 100644 spec/services/projects/gitlab_projects_import_service_spec.rb diff --git a/app/services/projects/gitlab_projects_import_service.rb b/app/services/projects/gitlab_projects_import_service.rb index 4ca6414b73b..a3d7f5cbed5 100644 --- a/app/services/projects/gitlab_projects_import_service.rb +++ b/app/services/projects/gitlab_projects_import_service.rb @@ -26,7 +26,7 @@ module Projects end def tmp_filename - "#{SecureRandom.hex}_#{params[:path]}" + SecureRandom.hex end def file diff --git a/spec/controllers/import/gitlab_projects_controller_spec.rb b/spec/controllers/import/gitlab_projects_controller_spec.rb new file mode 100644 index 00000000000..8759d3c0b97 --- /dev/null +++ b/spec/controllers/import/gitlab_projects_controller_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Import::GitlabProjectsController do + set(:namespace) { create(:namespace) } + set(:user) { namespace.owner } + let(:file) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } + + before do + sign_in(user) + end + + describe 'POST create' do + context 'with an invalid path' do + it 'redirects with an error' do + post :create, namespace_id: namespace.id, path: '/test', file: file + + expect(flash[:alert]).to start_with('Project could not be imported') + expect(response).to have_gitlab_http_status(302) + end + + it 'redirects with an error when a relative path is used' do + post :create, namespace_id: namespace.id, path: '../test', file: file + + expect(flash[:alert]).to start_with('Project could not be imported') + expect(response).to have_gitlab_http_status(302) + end + end + + context 'with a valid path' do + it 'redirects to the new project path' do + post :create, namespace_id: namespace.id, path: 'test', file: file + + expect(flash[:notice]).to include('is being imported') + expect(response).to have_gitlab_http_status(302) + end + end + end +end diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index 026aa03f7cf..8505c0e0148 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -32,7 +32,7 @@ feature 'Import/Export - project import integration test', :js do expect(page).to have_content('Import an exported GitLab project') expect(URI.parse(current_url).query).to eq("namespace_id=#{namespace.id}&path=#{project_path}") - expect(Gitlab::ImportExport).to receive(:import_upload_path).with(filename: /\A\h{32}_test-project-path\h*\z/).and_call_original + expect(Gitlab::ImportExport).to receive(:import_upload_path).with(filename: /\A\h{32}\z/).and_call_original attach_file('file', file) click_on 'Import project' diff --git a/spec/services/projects/gitlab_projects_import_service_spec.rb b/spec/services/projects/gitlab_projects_import_service_spec.rb new file mode 100644 index 00000000000..bb0e274c93e --- /dev/null +++ b/spec/services/projects/gitlab_projects_import_service_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe Projects::GitlabProjectsImportService do + set(:namespace) { build(:namespace) } + let(:file) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } + subject { described_class.new(namespace.owner, { namespace_id: namespace.id, path: path, file: file }) } + + describe '#execute' do + context 'with an invalid path' do + let(:path) { '/invalid-path/' } + + it 'returns an invalid project' do + project = subject.execute + + expect(project).not_to be_persisted + expect(project).not_to be_valid + end + end + + context 'with a valid path' do + let(:path) { 'test-path' } + + it 'creates a project' do + project = subject.execute + + expect(project).to be_persisted + expect(project).to be_valid + end + end + end +end -- GitLab From 62b0e7f196123ebfacb1d96ac7c3c7d11a81d988 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 3 Jan 2018 18:01:02 +0000 Subject: [PATCH 140/149] Merge branch 'security-ac/fix-path-traversal-10-1' into 'security-10-1' [10.1] Fix path traversal in gitlab-ci.yml cache:key See merge request gitlab/gitlabhq!2272 (cherry picked from commit 991ae1d593e78e7c2484d5fe5b12dfce44a94bc8) 754c83ea Fix path traversal in gitlab-ci.yml cache:key --- changelogs/unreleased/security-10-3.yml | 5 ++ doc/ci/yaml/README.md | 2 +- lib/gitlab/ci/config/entry/validators.rb | 16 +++++- spec/lib/gitlab/ci/config/entry/key_spec.rb | 62 +++++++++++++++++++++ 4 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 changelogs/unreleased/security-10-3.yml diff --git a/changelogs/unreleased/security-10-3.yml b/changelogs/unreleased/security-10-3.yml new file mode 100644 index 00000000000..5c718d976cd --- /dev/null +++ b/changelogs/unreleased/security-10-3.yml @@ -0,0 +1,5 @@ +--- +title: Fix path traversal in gitlab-ci.yml cache:key +merge_request: +author: +type: security diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 38bd0450a09..99006aef301 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -252,7 +252,7 @@ The `cache:key` variable can use any of the [predefined variables](../variables/ The default key is **default** across the project, therefore everything is shared between each pipelines and jobs by default, starting from GitLab 9.0. ->**Note:** The `cache:key` variable cannot contain the `/` character. +>**Note:** The `cache:key` variable cannot contain the `/` character, or the equivalent URI encoded `%2F`; a value made only of dots (`.`, `%2E`) is also forbidden. --- diff --git a/lib/gitlab/ci/config/entry/validators.rb b/lib/gitlab/ci/config/entry/validators.rb index 0159179f0a9..bfc1d75cc70 100644 --- a/lib/gitlab/ci/config/entry/validators.rb +++ b/lib/gitlab/ci/config/entry/validators.rb @@ -64,10 +64,24 @@ module Gitlab include LegacyValidationHelpers def validate_each(record, attribute, value) - unless validate_string(value) + if validate_string(value) + validate_path(record, attribute, value) + else record.errors.add(attribute, 'should be a string or symbol') end end + + private + + def validate_path(record, attribute, value) + path = CGI.unescape(value.to_s) + + if path.include?('/') + record.errors.add(attribute, 'cannot contain the "/" character') + elsif path == '.' || path == '..' + record.errors.add(attribute, 'cannot be "." or ".."') + end + end end class RegexpValidator < ActiveModel::EachValidator diff --git a/spec/lib/gitlab/ci/config/entry/key_spec.rb b/spec/lib/gitlab/ci/config/entry/key_spec.rb index 5d4de60bc8a..846f5f44470 100644 --- a/spec/lib/gitlab/ci/config/entry/key_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/key_spec.rb @@ -4,6 +4,26 @@ describe Gitlab::Ci::Config::Entry::Key do let(:entry) { described_class.new(config) } describe 'validations' do + shared_examples 'key with slash' do + it 'is invalid' do + expect(entry).not_to be_valid + end + + it 'reports errors with config value' do + expect(entry.errors).to include 'key config cannot contain the "/" character' + end + end + + shared_examples 'key with only dots' do + it 'is invalid' do + expect(entry).not_to be_valid + end + + it 'reports errors with config value' do + expect(entry.errors).to include 'key config cannot be "." or ".."' + end + end + context 'when entry config value is correct' do let(:config) { 'test' } @@ -30,6 +50,48 @@ describe Gitlab::Ci::Config::Entry::Key do end end end + + context 'when entry value contains slash' do + let(:config) { 'key/with/some/slashes' } + + it_behaves_like 'key with slash' + end + + context 'when entry value contains URI encoded slash (%2F)' do + let(:config) { 'key%2Fwith%2Fsome%2Fslashes' } + + it_behaves_like 'key with slash' + end + + context 'when entry value is a dot' do + let(:config) { '.' } + + it_behaves_like 'key with only dots' + end + + context 'when entry value is two dots' do + let(:config) { '..' } + + it_behaves_like 'key with only dots' + end + + context 'when entry value is a URI encoded dot (%2E)' do + let(:config) { '%2e' } + + it_behaves_like 'key with only dots' + end + + context 'when entry value is two URI encoded dots (%2E)' do + let(:config) { '%2E%2e' } + + it_behaves_like 'key with only dots' + end + + context 'when entry value is one dot and one URI encoded dot' do + let(:config) { '.%2e' } + + it_behaves_like 'key with only dots' + end end describe '.default' do -- GitLab From a9dafaaa29b5c47c44da8a5bd1fd52f0c209c8a7 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 5 Jan 2018 17:55:51 +0000 Subject: [PATCH 141/149] Merge branch '41567-projectfix-10-1' into 'security-10-1' [10.1] backport - check project access on MR create See merge request gitlab/gitlabhq!2280 (cherry picked from commit 6ca3de3c1e97590f62677227c7eef2f000db766c) 285551b9 check project access on MR create --- app/services/merge_requests/create_service.rb | 28 +++++++-- changelogs/unreleased/projectfix.yml | 6 ++ spec/features/cycle_analytics_spec.rb | 1 + .../microsoft_teams_service_spec.rb | 4 ++ spec/requests/api/merge_requests_spec.rb | 26 +++++--- spec/requests/api/v3/merge_requests_spec.rb | 26 +++++--- .../merge_requests/create_service_spec.rb | 61 +++++++++++++++++++ ...attermost_notifications_shared_examples.rb | 1 + 8 files changed, 133 insertions(+), 20 deletions(-) create mode 100644 changelogs/unreleased/projectfix.yml diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb index 820709583fa..2e98e0a78b7 100644 --- a/app/services/merge_requests/create_service.rb +++ b/app/services/merge_requests/create_service.rb @@ -1,15 +1,11 @@ module MergeRequests class CreateService < MergeRequests::BaseService def execute - # @project is used to determine whether the user can set the merge request's - # assignee, milestone and labels. Whether they can depends on their - # permissions on the target project. - source_project = @project - @project = Project.find(params[:target_project_id]) if params[:target_project_id] + set_projects! merge_request = MergeRequest.new merge_request.target_project = @project - merge_request.source_project = source_project + merge_request.source_project = @source_project merge_request.source_branch = params[:source_branch] merge_request.merge_params['force_remove_source_branch'] = params.delete(:force_remove_source_branch) @@ -52,5 +48,25 @@ module MergeRequests pipelines.order(id: :desc).first end + + def set_projects! + # @project is used to determine whether the user can set the merge request's + # assignee, milestone and labels. Whether they can depends on their + # permissions on the target project. + @source_project = @project + @project = Project.find(params[:target_project_id]) if params[:target_project_id] + + # make sure that source/target project ids are not in + # params so it can't be overridden later when updating attributes + # from params when applying quick actions + params.delete(:source_project_id) + params.delete(:target_project_id) + + unless can?(current_user, :read_project, @source_project) && + can?(current_user, :read_project, @project) + + raise Gitlab::Access::AccessDeniedError + end + end end end diff --git a/changelogs/unreleased/projectfix.yml b/changelogs/unreleased/projectfix.yml new file mode 100644 index 00000000000..4d8ebe6194a --- /dev/null +++ b/changelogs/unreleased/projectfix.yml @@ -0,0 +1,6 @@ +--- +title: Check user authorization for source and target projects when creating a merge + request. +merge_request: +author: +type: security diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb index 177cd50dd72..2dac3502209 100644 --- a/spec/features/cycle_analytics_spec.rb +++ b/spec/features/cycle_analytics_spec.rb @@ -113,6 +113,7 @@ feature 'Cycle Analytics', :js do context "as a guest" do before do + project.add_developer(user) project.add_guest(guest) allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue]) diff --git a/spec/models/project_services/microsoft_teams_service_spec.rb b/spec/models/project_services/microsoft_teams_service_spec.rb index f89be20ad78..3b260d66a2a 100644 --- a/spec/models/project_services/microsoft_teams_service_spec.rb +++ b/spec/models/project_services/microsoft_teams_service_spec.rb @@ -92,6 +92,10 @@ describe MicrosoftTeamsService do service.hook_data(merge_request, 'open') end + before do + project.add_developer(user) + end + it "calls Microsoft Teams API" do chat_service.execute(merge_sample_data) diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 5e66e1607ba..971e522076b 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -677,16 +677,28 @@ describe API::MergeRequests do expect(response).to have_gitlab_http_status(400) end - context 'when target_branch is specified' do + context 'when target_branch and target_project_id is specified' do + let(:params) do + { title: 'Test merge_request', + target_branch: 'master', + source_branch: 'markdown', + author: user2, + target_project_id: unrelated_project.id } + end + it 'returns 422 if targeting a different fork' do - post api("/projects/#{forked_project.id}/merge_requests", user2), - title: 'Test merge_request', - target_branch: 'master', - source_branch: 'markdown', - author: user2, - target_project_id: unrelated_project.id + unrelated_project.add_developer(user2) + + post api("/projects/#{forked_project.id}/merge_requests", user2), params + expect(response).to have_gitlab_http_status(422) end + + it 'returns 403 if targeting a different fork which user can not access' do + post api("/projects/#{forked_project.id}/merge_requests", user2), params + + expect(response).to have_gitlab_http_status(403) + end end it "returns 201 when target_branch is specified and for the same project" do diff --git a/spec/requests/api/v3/merge_requests_spec.rb b/spec/requests/api/v3/merge_requests_spec.rb index df73c731c96..bb327604be4 100644 --- a/spec/requests/api/v3/merge_requests_spec.rb +++ b/spec/requests/api/v3/merge_requests_spec.rb @@ -373,16 +373,28 @@ describe API::MergeRequests do expect(response).to have_gitlab_http_status(400) end - context 'when target_branch is specified' do + context 'when target_branch and target_project_id is specified' do + let(:params) do + { title: 'Test merge_request', + target_branch: 'master', + source_branch: 'markdown', + author: user2, + target_project_id: unrelated_project.id } + end + it 'returns 422 if targeting a different fork' do - post v3_api("/projects/#{forked_project.id}/merge_requests", user2), - title: 'Test merge_request', - target_branch: 'master', - source_branch: 'markdown', - author: user2, - target_project_id: unrelated_project.id + unrelated_project.add_developer(user2) + + post v3_api("/projects/#{forked_project.id}/merge_requests", user2), params + expect(response).to have_gitlab_http_status(422) end + + it 'returns 403 if targeting a different fork which user can not access' do + post v3_api("/projects/#{forked_project.id}/merge_requests", user2), params + + expect(response).to have_gitlab_http_status(403) + end end it "returns 201 when target_branch is specified and for the same project" do diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb index a047f891ab2..8f35c8c42f6 100644 --- a/spec/services/merge_requests/create_service_spec.rb +++ b/spec/services/merge_requests/create_service_spec.rb @@ -263,5 +263,66 @@ describe MergeRequests::CreateService do expect(issue_ids).to match_array([first_issue.id, second_issue.id]) end end + + context 'when source and target projects are different' do + let(:target_project) { create(:project) } + + let(:opts) do + { + title: 'Awesome merge_request', + source_branch: 'feature', + target_branch: 'master', + target_project_id: target_project.id + } + end + + context 'when user can not access source project' do + before do + target_project.add_developer(assignee) + target_project.add_master(user) + end + + it 'raises an error' do + expect { described_class.new(project, user, opts).execute } + .to raise_error Gitlab::Access::AccessDeniedError + end + end + + context 'when user can not access target project' do + before do + target_project.add_developer(assignee) + target_project.add_master(user) + end + + it 'raises an error' do + expect { described_class.new(project, user, opts).execute } + .to raise_error Gitlab::Access::AccessDeniedError + end + end + end + + context 'when user sets source project id' do + let(:another_project) { create(:project) } + + let(:opts) do + { + title: 'Awesome merge_request', + source_branch: 'feature', + target_branch: 'master', + source_project_id: another_project.id + } + end + + before do + project.add_developer(assignee) + project.add_master(user) + end + + it 'ignores source_project_id' do + merge_request = described_class.new(project, user, opts).execute + + expect(merge_request.source_project_id).to eq(project.id) + end + end end end diff --git a/spec/support/slack_mattermost_notifications_shared_examples.rb b/spec/support/slack_mattermost_notifications_shared_examples.rb index 6accf16bea4..9fcaf04fb3d 100644 --- a/spec/support/slack_mattermost_notifications_shared_examples.rb +++ b/spec/support/slack_mattermost_notifications_shared_examples.rb @@ -57,6 +57,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do @issue = issue_service.execute @issues_sample_data = issue_service.hook_data(@issue, 'open') + project.add_developer(user) opts = { title: 'Awesome merge_request', description: 'please fix', -- GitLab From 237d2da409fa69cfb5a9b85cbe7b71381a96993e Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 5 Jan 2018 15:23:46 +0000 Subject: [PATCH 142/149] Merge branch 'sh-migrate-can-push-to-deploy-keys-projects-10-1' into 'security-10-1' [10.1] Migrate `can_push` column from `keys` to `deploy_keys_project` See merge request gitlab/gitlabhq!2274 (cherry picked from commit b8ed2ac5bf4a75d0787315e741d4c9aacd36e07e) 5f214517 Backport to 10.1 --- .../deploy_keys/components/key.vue | 27 +++++--- .../admin/deploy_keys_controller.rb | 4 +- .../projects/deploy_keys_controller.rb | 9 ++- app/models/deploy_key.rb | 20 +++++- app/models/deploy_keys_project.rb | 10 ++- .../settings/deploy_keys_presenter.rb | 2 +- app/serializers/deploy_key_entity.rb | 9 +-- app/serializers/deploy_keys_project_entity.rb | 4 ++ app/views/admin/deploy_keys/index.html.haml | 9 ++- .../projects/deploy_keys/_form.html.haml | 18 +++--- app/views/shared/deploy_keys/_form.html.haml | 19 +++--- ...grate-can-push-to-deploy-keys-projects.yml | 5 ++ ...25_add_can_push_to_deploy_keys_projects.rb | 15 +++++ ...late_can_push_from_deploy_keys_projects.rb | 44 +++++++++++++ ...late_can_push_from_deploy_keys_projects.rb | 43 +++++++++++++ ...0171215121259_remove_can_push_from_keys.rb | 17 +++++ db/schema.rb | 4 +- doc/api/deploy_keys.md | 48 +++++++++++--- lib/api/deploy_keys.rb | 64 +++++++++++++------ lib/api/entities.rb | 7 +- lib/api/v3/deploy_keys.rb | 46 +++++++++---- spec/factories/deploy_keys_projects.rb | 4 ++ spec/factories/keys.rb | 4 -- spec/features/admin/admin_deploy_keys_spec.rb | 14 ++-- .../settings/repository_settings_spec.rb | 6 +- .../deploy_keys/components/key_spec.js | 20 ++++-- spec/lib/gitlab/git_access_spec.rb | 14 ++-- spec/models/deploy_keys_project_spec.rb | 2 +- spec/requests/api/deploy_keys_spec.rb | 12 +--- spec/requests/api/v3/deploy_keys_spec.rb | 2 +- spec/serializers/deploy_key_entity_spec.rb | 15 +++-- 31 files changed, 380 insertions(+), 137 deletions(-) create mode 100644 app/serializers/deploy_keys_project_entity.rb create mode 100644 changelogs/unreleased/sh-migrate-can-push-to-deploy-keys-projects.yml create mode 100644 db/migrate/20171211145425_add_can_push_to_deploy_keys_projects.rb create mode 100644 db/migrate/20171215113714_populate_can_push_from_deploy_keys_projects.rb create mode 100644 db/post_migrate/20171215121205_post_populate_can_push_from_deploy_keys_projects.rb create mode 100644 db/post_migrate/20171215121259_remove_can_push_from_keys.rb diff --git a/app/assets/javascripts/deploy_keys/components/key.vue b/app/assets/javascripts/deploy_keys/components/key.vue index b41d464475f..7df2440a7c4 100644 --- a/app/assets/javascripts/deploy_keys/components/key.vue +++ b/app/assets/javascripts/deploy_keys/components/key.vue @@ -1,5 +1,6 @@ @@ -51,20 +58,22 @@
{{ deployKey.fingerprint }}
-
- Write access allowed -
diff --git a/app/controllers/admin/deploy_keys_controller.rb b/app/controllers/admin/deploy_keys_controller.rb index a7ab481519d..b0c4c31cffc 100644 --- a/app/controllers/admin/deploy_keys_controller.rb +++ b/app/controllers/admin/deploy_keys_controller.rb @@ -50,10 +50,10 @@ class Admin::DeployKeysController < Admin::ApplicationController end def create_params - params.require(:deploy_key).permit(:key, :title, :can_push) + params.require(:deploy_key).permit(:key, :title) end def update_params - params.require(:deploy_key).permit(:title, :can_push) + params.require(:deploy_key).permit(:title) end end diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb index cf8829ba95b..103079888b2 100644 --- a/app/controllers/projects/deploy_keys_controller.rb +++ b/app/controllers/projects/deploy_keys_controller.rb @@ -24,7 +24,7 @@ class Projects::DeployKeysController < Projects::ApplicationController def create @key = DeployKeys::CreateService.new(current_user, create_params).execute - unless @key.valid? && @project.deploy_keys << @key + unless @key.valid? flash[:alert] = @key.errors.full_messages.join(', ').html_safe end redirect_to_repository_settings(@project) @@ -70,11 +70,14 @@ class Projects::DeployKeysController < Projects::ApplicationController end def create_params - params.require(:deploy_key).permit(:key, :title, :can_push) + create_params = params.require(:deploy_key) + .permit(:key, :title, deploy_keys_projects_attributes: [:can_push]) + create_params.dig(:deploy_keys_projects_attributes, '0')&.merge!(project_id: @project.id) + create_params end def update_params - params.require(:deploy_key).permit(:title, :can_push) + params.require(:deploy_key).permit(:title, deploy_keys_projects_attributes: [:id, :can_push]) end def authorize_update_deploy_key! diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb index eae5eee4fee..c2e0a5fa126 100644 --- a/app/models/deploy_key.rb +++ b/app/models/deploy_key.rb @@ -1,10 +1,16 @@ class DeployKey < Key - has_many :deploy_keys_projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent + include IgnorableColumn + + has_many :deploy_keys_projects, inverse_of: :deploy_key, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :projects, through: :deploy_keys_projects scope :in_projects, ->(projects) { joins(:deploy_keys_projects).where('deploy_keys_projects.project_id in (?)', projects) } scope :are_public, -> { where(public: true) } + ignore_column :can_push + + accepts_nested_attributes_for :deploy_keys_projects + def private? !public? end @@ -22,10 +28,18 @@ class DeployKey < Key end def has_access_to?(project) - projects.include?(project) + deploy_keys_project_for(project).present? end def can_push_to?(project) - can_push? && has_access_to?(project) + !!deploy_keys_project_for(project)&.can_push? + end + + def deploy_keys_project_for(project) + deploy_keys_projects.find_by(project: project) + end + + def projects_with_write_access + Project.preload(:route).where(id: deploy_keys_projects.with_write_access.select(:project_id)) end end diff --git a/app/models/deploy_keys_project.rb b/app/models/deploy_keys_project.rb index b37b9bfbdac..6eef12c4373 100644 --- a/app/models/deploy_keys_project.rb +++ b/app/models/deploy_keys_project.rb @@ -1,8 +1,14 @@ class DeployKeysProject < ActiveRecord::Base belongs_to :project - belongs_to :deploy_key + belongs_to :deploy_key, inverse_of: :deploy_keys_projects - validates :deploy_key_id, presence: true + scope :without_project_deleted, -> { joins(:project).where(projects: { pending_delete: false }) } + scope :in_project, ->(project) { where(project: project) } + scope :with_write_access, -> { where(can_push: true) } + + accepts_nested_attributes_for :deploy_key + + validates :deploy_key, presence: true validates :deploy_key_id, uniqueness: { scope: [:project_id], message: "already exists in project" } validates :project_id, presence: true diff --git a/app/presenters/projects/settings/deploy_keys_presenter.rb b/app/presenters/projects/settings/deploy_keys_presenter.rb index 229311eb6ee..c226586fba5 100644 --- a/app/presenters/projects/settings/deploy_keys_presenter.rb +++ b/app/presenters/projects/settings/deploy_keys_presenter.rb @@ -7,7 +7,7 @@ module Projects delegate :size, to: :available_public_keys, prefix: true def new_key - @key ||= DeployKey.new + @key ||= DeployKey.new.tap { |dk| dk.deploy_keys_projects.build } end def enabled_keys diff --git a/app/serializers/deploy_key_entity.rb b/app/serializers/deploy_key_entity.rb index c75431a79ae..2678f99510c 100644 --- a/app/serializers/deploy_key_entity.rb +++ b/app/serializers/deploy_key_entity.rb @@ -3,19 +3,20 @@ class DeployKeyEntity < Grape::Entity expose :user_id expose :title expose :fingerprint - expose :can_push expose :destroyed_when_orphaned?, as: :destroyed_when_orphaned expose :almost_orphaned?, as: :almost_orphaned expose :created_at expose :updated_at - expose :projects, using: ProjectEntity do |deploy_key| - deploy_key.projects.without_deleted.select { |project| options[:user].can?(:read_project, project) } + expose :deploy_keys_projects, using: DeployKeysProjectEntity do |deploy_key| + deploy_key.deploy_keys_projects + .without_project_deleted + .select { |deploy_key_project| Ability.allowed?(options[:user], :read_project, deploy_key_project.project) } end expose :can_edit private def can_edit - options[:user].can?(:update_deploy_key, object) + Ability.allowed?(options[:user], :update_deploy_key, object) end end diff --git a/app/serializers/deploy_keys_project_entity.rb b/app/serializers/deploy_keys_project_entity.rb new file mode 100644 index 00000000000..568ef5ab75e --- /dev/null +++ b/app/serializers/deploy_keys_project_entity.rb @@ -0,0 +1,4 @@ +class DeployKeysProjectEntity < Grape::Entity + expose :can_push + expose :project, using: ProjectEntity +end diff --git a/app/views/admin/deploy_keys/index.html.haml b/app/views/admin/deploy_keys/index.html.haml index 92370034baa..09d13334b6e 100644 --- a/app/views/admin/deploy_keys/index.html.haml +++ b/app/views/admin/deploy_keys/index.html.haml @@ -12,7 +12,7 @@ %tr %th.col-sm-2 Title %th.col-sm-4 Fingerprint - %th.col-sm-2 Write access allowed + %th.col-sm-2 Projects with write access %th.col-sm-2 Added at %th.col-sm-2 %tbody @@ -23,10 +23,9 @@ %td %code.key-fingerprint= deploy_key.fingerprint %td - - if deploy_key.can_push? - Yes - - else - No + - deploy_key.projects_with_write_access.each do |project| + = link_to project.full_name, admin_project_path(project), class: 'label deploy-project-label' + %td %span.cgray added #{time_ago_with_tooltip(deploy_key.created_at)} diff --git a/app/views/projects/deploy_keys/_form.html.haml b/app/views/projects/deploy_keys/_form.html.haml index edaa3a1119e..f9355a31b65 100644 --- a/app/views/projects/deploy_keys/_form.html.haml +++ b/app/views/projects/deploy_keys/_form.html.haml @@ -10,13 +10,15 @@ %p.light.append-bottom-0 Paste a machine public key here. Read more about how to generate it = link_to "here", help_page_path("ssh/README") - .form-group - .checkbox - = f.label :can_push do - = f.check_box :can_push - %strong Write access allowed - .form-group - %p.light.append-bottom-0 - Allow this key to push to repository as well? (Default only allows pull access.) + = f.fields_for :deploy_keys_projects do |deploy_keys_project_form| + .form-group + .checkbox + = deploy_keys_project_form.label :can_push do + = deploy_keys_project_form.check_box :can_push + %strong Write access allowed + .form-group + %p.light.append-bottom-0 + Allow this key to push to repository as well? (Default only allows pull access.) + = f.submit "Add key", class: "btn-create btn" diff --git a/app/views/shared/deploy_keys/_form.html.haml b/app/views/shared/deploy_keys/_form.html.haml index e6075c3ae3a..87c2965bb21 100644 --- a/app/views/shared/deploy_keys/_form.html.haml +++ b/app/views/shared/deploy_keys/_form.html.haml @@ -1,5 +1,6 @@ - form = local_assigns.fetch(:form) - deploy_key = local_assigns.fetch(:deploy_key) +- deploy_keys_project = deploy_key.deploy_keys_project_for(@project) = form_errors(deploy_key) @@ -20,11 +21,13 @@ .col-sm-10 = form.text_field :fingerprint, class: 'form-control', readonly: 'readonly' -.form-group - .control-label - .col-sm-10 - = form.label :can_push do - = form.check_box :can_push - %strong Write access allowed - %p.light.append-bottom-0 - Allow this key to push to repository as well? (Default only allows pull access.) +- if deploy_keys_project.present? + = form.fields_for :deploy_keys_projects, deploy_keys_project do |deploy_keys_project_form| + .form-group + .control-label + .col-sm-10 + = deploy_keys_project_form.label :can_push do + = deploy_keys_project_form.check_box :can_push + %strong Write access allowed + %p.light.append-bottom-0 + Allow this key to push to repository as well? (Default only allows pull access.) diff --git a/changelogs/unreleased/sh-migrate-can-push-to-deploy-keys-projects.yml b/changelogs/unreleased/sh-migrate-can-push-to-deploy-keys-projects.yml new file mode 100644 index 00000000000..cb53a94e465 --- /dev/null +++ b/changelogs/unreleased/sh-migrate-can-push-to-deploy-keys-projects.yml @@ -0,0 +1,5 @@ +--- +title: Fix writable shared deploy keys +merge_request: +author: +type: security diff --git a/db/migrate/20171211145425_add_can_push_to_deploy_keys_projects.rb b/db/migrate/20171211145425_add_can_push_to_deploy_keys_projects.rb new file mode 100644 index 00000000000..5dc723db9f9 --- /dev/null +++ b/db/migrate/20171211145425_add_can_push_to_deploy_keys_projects.rb @@ -0,0 +1,15 @@ +class AddCanPushToDeployKeysProjects < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + disable_ddl_transaction! + + def up + add_column_with_default :deploy_keys_projects, :can_push, :boolean, default: false, allow_null: false + end + + def down + remove_column :deploy_keys_projects, :can_push + end +end diff --git a/db/migrate/20171215113714_populate_can_push_from_deploy_keys_projects.rb b/db/migrate/20171215113714_populate_can_push_from_deploy_keys_projects.rb new file mode 100644 index 00000000000..ec0427a8e5a --- /dev/null +++ b/db/migrate/20171215113714_populate_can_push_from_deploy_keys_projects.rb @@ -0,0 +1,44 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class PopulateCanPushFromDeployKeysProjects < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + disable_ddl_transaction! + + class DeploysKeyProject < ActiveRecord::Base + include EachBatch + + self.table_name = 'deploy_keys_projects' + end + + def up + DeploysKeyProject.each_batch(of: 10_000) do |batch| + start_id, end_id = batch.pluck('MIN(id), MAX(id)').first + + execute <<-EOF + UPDATE deploy_keys_projects + SET can_push = keys.can_push + FROM keys + WHERE deploy_key_id = keys.id + AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} + EOF + end + end + + def down + DeploysKeyProject.each_batch(of: 10_000) do |batch| + start_id, end_id = batch.pluck('MIN(id), MAX(id)').first + + execute <<-EOF + UPDATE keys + SET can_push = deploy_keys_projects.can_push + FROM deploy_keys_projects + WHERE deploy_keys_projects.deploy_key_id = keys.id + AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} + EOF + end + end +end diff --git a/db/post_migrate/20171215121205_post_populate_can_push_from_deploy_keys_projects.rb b/db/post_migrate/20171215121205_post_populate_can_push_from_deploy_keys_projects.rb new file mode 100644 index 00000000000..05d236f8e96 --- /dev/null +++ b/db/post_migrate/20171215121205_post_populate_can_push_from_deploy_keys_projects.rb @@ -0,0 +1,43 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class PostPopulateCanPushFromDeployKeysProjects < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + disable_ddl_transaction! + + class DeploysKeyProject < ActiveRecord::Base + include EachBatch + + self.table_name = 'deploy_keys_projects' + end + + def up + DeploysKeyProject.each_batch(of: 10_000) do |batch| + start_id, end_id = batch.pluck('MIN(id), MAX(id)').first + + execute <<-EOF + UPDATE deploy_keys_projects + SET can_push = keys.can_push + FROM keys + WHERE deploy_key_id = keys.id + AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} + EOF + end + end + + def down + DeploysKeyProject.each_batch(of: 10_000) do |batch| + start_id, end_id = batch.pluck('MIN(id), MAX(id)').first + + execute <<-EOF + UPDATE keys + SET can_push = deploy_keys_projects.can_push + FROM deploy_keys_projects + WHERE deploy_keys_projects.deploy_key_id = keys.id + AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} + EOF + end + end +end diff --git a/db/post_migrate/20171215121259_remove_can_push_from_keys.rb b/db/post_migrate/20171215121259_remove_can_push_from_keys.rb new file mode 100644 index 00000000000..0599811d986 --- /dev/null +++ b/db/post_migrate/20171215121259_remove_can_push_from_keys.rb @@ -0,0 +1,17 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class RemoveCanPushFromKeys < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + disable_ddl_transaction! + + def up + remove_column :keys, :can_push + end + + def down + add_column_with_default :keys, :can_push, :boolean, default: false, allow_null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index d26481625c7..307e451c3b9 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20171017145932) do +ActiveRecord::Schema.define(version: 20171215121259) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -512,6 +512,7 @@ ActiveRecord::Schema.define(version: 20171017145932) do t.integer "project_id", null: false t.datetime "created_at" t.datetime "updated_at" + t.boolean "can_push", default: false, null: false end add_index "deploy_keys_projects", ["project_id"], name: "index_deploy_keys_projects_on_project_id", using: :btree @@ -774,7 +775,6 @@ ActiveRecord::Schema.define(version: 20171017145932) do t.string "type" t.string "fingerprint" t.boolean "public", default: false, null: false - t.boolean "can_push", default: false, null: false t.datetime "last_used_at" end diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md index 273d5a56b6f..698fa22a438 100644 --- a/doc/api/deploy_keys.md +++ b/doc/api/deploy_keys.md @@ -19,15 +19,13 @@ Example response: { "id": 1, "title": "Public key", - "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", - "can_push": false, + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2013-10-02T10:12:29Z" }, { "id": 3, "title": "Another Public key", - "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", - "can_push": true, + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", "created_at": "2013-10-02T11:12:29Z" } ] @@ -57,15 +55,15 @@ Example response: "id": 1, "title": "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", - "can_push": false, - "created_at": "2013-10-02T10:12:29Z" + "created_at": "2013-10-02T10:12:29Z", + "can_push": false }, { "id": 3, "title": "Another Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", - "can_push": false, - "created_at": "2013-10-02T11:12:29Z" + "created_at": "2013-10-02T11:12:29Z", + "can_push": false } ] ``` @@ -96,8 +94,8 @@ Example response: "id": 1, "title": "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", - "can_push": false, - "created_at": "2013-10-02T10:12:29Z" + "created_at": "2013-10-02T10:12:29Z", + "can_push": false } ``` @@ -135,6 +133,36 @@ Example response: } ``` +## Update deploy key + +Updates a deploy key for a project. + +``` +PUT /projects/:id/deploy_keys/:key_id +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | +| `title` | string | no | New deploy key's title | +| `can_push` | boolean | no | Can deploy key push to the project's repository | + +```bash +curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "Content-Type: application/json" --data '{"title": "New deploy key", "can_push": true}' "https://gitlab.example.com/api/v4/projects/5/deploy_keys/11" +``` + +Example response: + +```json +{ + "id": 11, + "title": "New deploy key", + "key": "ssh-rsa AAAA...", + "created_at": "2015-08-29T12:44:31.550Z", + "can_push": true +} +``` + ## Delete deploy key Removes a deploy key from the project. If the deploy key is used only for this project, it will be deleted from the system. diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb index 281269b1190..a92f17937b8 100644 --- a/lib/api/deploy_keys.rb +++ b/lib/api/deploy_keys.rb @@ -4,6 +4,16 @@ module API before { authenticate! } + helpers do + def add_deploy_keys_project(project, attrs = {}) + project.deploy_keys_projects.create(attrs) + end + + def find_by_deploy_key(project, key_id) + project.deploy_keys_projects.find_by!(deploy_key: key_id) + end + end + desc 'Return all deploy keys' params do use :pagination @@ -21,28 +31,31 @@ module API before { authorize_admin_project } desc "Get a specific project's deploy keys" do - success Entities::SSHKey + success Entities::DeployKeysProject end params do use :pagination end get ":id/deploy_keys" do - present paginate(user_project.deploy_keys), with: Entities::SSHKey + keys = user_project.deploy_keys_projects.preload(:deploy_key) + + present paginate(keys), with: Entities::DeployKeysProject end desc 'Get single deploy key' do - success Entities::SSHKey + success Entities::DeployKeysProject end params do requires :key_id, type: Integer, desc: 'The ID of the deploy key' end get ":id/deploy_keys/:key_id" do - key = user_project.deploy_keys.find params[:key_id] - present key, with: Entities::SSHKey + key = find_by_deploy_key(user_project, params[:key_id]) + + present key, with: Entities::DeployKeysProject end desc 'Add new deploy key to currently authenticated user' do - success Entities::SSHKey + success Entities::DeployKeysProject end params do requires :key, type: String, desc: 'The new deploy key' @@ -53,24 +66,31 @@ module API params[:key].strip! # Check for an existing key joined to this project - key = user_project.deploy_keys.find_by(key: params[:key]) + key = user_project.deploy_keys_projects + .joins(:deploy_key) + .find_by(keys: { key: params[:key] }) + if key - present key, with: Entities::SSHKey + present key, with: Entities::DeployKeysProject break end # Check for available deploy keys in other projects key = current_user.accessible_deploy_keys.find_by(key: params[:key]) if key - user_project.deploy_keys << key - present key, with: Entities::SSHKey + added_key = add_deploy_keys_project(user_project, deploy_key: key, can_push: !!params[:can_push]) + + present added_key, with: Entities::DeployKeysProject break end # Create a new deploy key - key = DeployKey.new(declared_params(include_missing: false)) - if key.valid? && user_project.deploy_keys << key - present key, with: Entities::SSHKey + key_attributes = { can_push: !!params[:can_push], + deploy_key_attributes: declared_params.except(:can_push) } + key = add_deploy_keys_project(user_project, key_attributes) + + if key.valid? + present key, with: Entities::DeployKeysProject else render_validation_error!(key) end @@ -86,14 +106,20 @@ module API at_least_one_of :title, :can_push end put ":id/deploy_keys/:key_id" do - key = DeployKey.find(params.delete(:key_id)) + deploy_keys_project = find_by_deploy_key(user_project, params[:key_id]) - authorize!(:update_deploy_key, key) + authorize!(:update_deploy_key, deploy_keys_project.deploy_key) - if key.update_attributes(declared_params(include_missing: false)) - present key, with: Entities::SSHKey + can_push = params[:can_push].nil? ? deploy_keys_project.can_push : params[:can_push] + title = params[:title] || deploy_keys_project.deploy_key.title + + result = deploy_keys_project.update_attributes(can_push: can_push, + deploy_key_attributes: { id: params[:key_id], + title: title }) + if result + present deploy_keys_project, with: Entities::DeployKeysProject else - render_validation_error!(key) + render_validation_error!(deploy_keys_project) end end @@ -122,7 +148,7 @@ module API requires :key_id, type: Integer, desc: 'The ID of the deploy key' end delete ":id/deploy_keys/:key_id" do - key = user_project.deploy_keys_projects.find_by(deploy_key_id: params[:key_id]) + key = user_project.deploy_keys.find(params[:key_id]) not_found!('Deploy Key') unless key destroy_conditionally!(key) diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 311a6dda200..a03f74c9aa1 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -504,13 +504,18 @@ module API end class SSHKey < Grape::Entity - expose :id, :title, :key, :created_at, :can_push + expose :id, :title, :key, :created_at end class SSHKeyWithUser < SSHKey expose :user, using: Entities::UserPublic end + class DeployKeysProject < Grape::Entity + expose :deploy_key, merge: true, using: Entities::SSHKey + expose :can_push + end + class GPGKey < Grape::Entity expose :id, :key, :created_at end diff --git a/lib/api/v3/deploy_keys.rb b/lib/api/v3/deploy_keys.rb index b90e2061da3..47e54ca85a5 100644 --- a/lib/api/v3/deploy_keys.rb +++ b/lib/api/v3/deploy_keys.rb @@ -3,6 +3,16 @@ module API class DeployKeys < Grape::API before { authenticate! } + helpers do + def add_deploy_keys_project(project, attrs = {}) + project.deploy_keys_projects.create(attrs) + end + + def find_by_deploy_key(project, key_id) + project.deploy_keys_projects.find_by!(deploy_key: key_id) + end + end + get "deploy_keys" do authenticated_as_admin! @@ -18,25 +28,28 @@ module API %w(keys deploy_keys).each do |path| desc "Get a specific project's deploy keys" do - success ::API::Entities::SSHKey + success ::API::Entities::DeployKeysProject end get ":id/#{path}" do - present user_project.deploy_keys, with: ::API::Entities::SSHKey + keys = user_project.deploy_keys_projects.preload(:deploy_key) + + present keys, with: ::API::Entities::DeployKeysProject end desc 'Get single deploy key' do - success ::API::Entities::SSHKey + success ::API::Entities::DeployKeysProject end params do requires :key_id, type: Integer, desc: 'The ID of the deploy key' end get ":id/#{path}/:key_id" do - key = user_project.deploy_keys.find params[:key_id] - present key, with: ::API::Entities::SSHKey + key = find_by_deploy_key(user_project, params[:key_id]) + + present key, with: ::API::Entities::DeployKeysProject end desc 'Add new deploy key to currently authenticated user' do - success ::API::Entities::SSHKey + success ::API::Entities::DeployKeysProject end params do requires :key, type: String, desc: 'The new deploy key' @@ -47,24 +60,31 @@ module API params[:key].strip! # Check for an existing key joined to this project - key = user_project.deploy_keys.find_by(key: params[:key]) + key = user_project.deploy_keys_projects + .joins(:deploy_key) + .find_by(keys: { key: params[:key] }) + if key - present key, with: ::API::Entities::SSHKey + present key, with: ::API::Entities::DeployKeysProject break end # Check for available deploy keys in other projects key = current_user.accessible_deploy_keys.find_by(key: params[:key]) if key - user_project.deploy_keys << key - present key, with: ::API::Entities::SSHKey + added_key = add_deploy_keys_project(user_project, deploy_key: key, can_push: !!params[:can_push]) + + present added_key, with: ::API::Entities::DeployKeysProject break end # Create a new deploy key - key = DeployKey.new(declared_params(include_missing: false)) - if key.valid? && user_project.deploy_keys << key - present key, with: ::API::Entities::SSHKey + key_attributes = { can_push: !!params[:can_push], + deploy_key_attributes: declared_params.except(:can_push) } + key = add_deploy_keys_project(user_project, key_attributes) + + if key.valid? + present key, with: ::API::Entities::DeployKeysProject else render_validation_error!(key) end diff --git a/spec/factories/deploy_keys_projects.rb b/spec/factories/deploy_keys_projects.rb index 27cece487bd..c7202714f21 100644 --- a/spec/factories/deploy_keys_projects.rb +++ b/spec/factories/deploy_keys_projects.rb @@ -2,5 +2,9 @@ FactoryGirl.define do factory :deploy_keys_project do deploy_key project + + trait :write_access do + can_push true + end end end diff --git a/spec/factories/keys.rb b/spec/factories/keys.rb index 3f7c794b14a..06055e5b201 100644 --- a/spec/factories/keys.rb +++ b/spec/factories/keys.rb @@ -15,10 +15,6 @@ FactoryGirl.define do factory :another_deploy_key, class: 'DeployKey' end - factory :write_access_key, class: 'DeployKey' do - can_push true - end - factory :rsa_key_2048 do key do 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFf6RYK3qu/RKF/3ndJmL5xgMLp3O9' \ diff --git a/spec/features/admin/admin_deploy_keys_spec.rb b/spec/features/admin/admin_deploy_keys_spec.rb index 241c7cbc34e..cb96830cb7c 100644 --- a/spec/features/admin/admin_deploy_keys_spec.rb +++ b/spec/features/admin/admin_deploy_keys_spec.rb @@ -17,6 +17,16 @@ RSpec.describe 'admin deploy keys' do end end + it 'shows all the projects the deploy key has write access' do + write_key = create(:deploy_keys_project, :write_access, deploy_key: deploy_key) + + visit admin_deploy_keys_path + + page.within(find('.deploy-keys-list', match: :first)) do + expect(page).to have_content(write_key.project.full_name) + end + end + describe 'create a new deploy key' do let(:new_ssh_key) { attributes_for(:key)[:key] } @@ -28,14 +38,12 @@ RSpec.describe 'admin deploy keys' do it 'creates a new deploy key' do fill_in 'deploy_key_title', with: 'laptop' fill_in 'deploy_key_key', with: new_ssh_key - check 'deploy_key_can_push' click_button 'Create' expect(current_path).to eq admin_deploy_keys_path page.within(find('.deploy-keys-list', match: :first)) do expect(page).to have_content('laptop') - expect(page).to have_content('Yes') end end end @@ -48,14 +56,12 @@ RSpec.describe 'admin deploy keys' do it 'updates an existing deploy key' do fill_in 'deploy_key_title', with: 'new-title' - check 'deploy_key_can_push' click_button 'Save changes' expect(current_path).to eq admin_deploy_keys_path page.within(find('.deploy-keys-list', match: :first)) do expect(page).to have_content('new-title') - expect(page).to have_content('Yes') end end end diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb index a4fefb0d0e7..b05aecc1198 100644 --- a/spec/features/projects/settings/repository_settings_spec.rb +++ b/spec/features/projects/settings/repository_settings_spec.rb @@ -44,7 +44,7 @@ feature 'Repository settings' do fill_in 'deploy_key_title', with: 'new_deploy_key' fill_in 'deploy_key_key', with: new_ssh_key - check 'deploy_key_can_push' + check 'deploy_key_deploy_keys_projects_attributes_0_can_push' click_button 'Add key' expect(page).to have_content('new_deploy_key') @@ -58,7 +58,7 @@ feature 'Repository settings' do find('li', text: private_deploy_key.title).click_link('Edit') fill_in 'deploy_key_title', with: 'updated_deploy_key' - check 'deploy_key_can_push' + check 'deploy_key_deploy_keys_projects_attributes_0_can_push' click_button 'Save changes' expect(page).to have_content('updated_deploy_key') @@ -75,11 +75,9 @@ feature 'Repository settings' do find('li', text: private_deploy_key.title).click_link('Edit') fill_in 'deploy_key_title', with: 'updated_deploy_key' - check 'deploy_key_can_push' click_button 'Save changes' expect(page).to have_content('updated_deploy_key') - expect(page).to have_content('Write access allowed') end scenario 'remove an existing deploy key' do diff --git a/spec/javascripts/deploy_keys/components/key_spec.js b/spec/javascripts/deploy_keys/components/key_spec.js index 5b64cbb2dfc..c253648007f 100644 --- a/spec/javascripts/deploy_keys/components/key_spec.js +++ b/spec/javascripts/deploy_keys/components/key_spec.js @@ -52,18 +52,24 @@ describe('Deploy keys key', () => { ).toBe('Remove'); }); - it('shows write access text when key has write access', (done) => { - vm.deployKey.can_push = true; + it('shows write access title when key has write access', (done) => { + vm.deployKey.deploy_keys_projects[0].can_push = true; Vue.nextTick(() => { expect( - vm.$el.querySelector('.write-access-allowed'), - ).not.toBeNull(); - - expect( - vm.$el.querySelector('.write-access-allowed').textContent.trim(), + vm.$el.querySelector('.deploy-project-label').getAttribute('data-original-title'), ).toBe('Write access allowed'); + done(); + }); + }); + + it('does not show write access title when key has write access', (done) => { + vm.deployKey.deploy_keys_projects[0].can_push = false; + Vue.nextTick(() => { + expect( + vm.$el.querySelector('.deploy-project-label').getAttribute('data-original-title'), + ).toBe('Read access only'); done(); }); }); diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index c9643c5da47..68d54722941 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -51,12 +51,12 @@ describe Gitlab::GitAccess do context 'when the project exists' do context 'when actor exists' do context 'when actor is a DeployKey' do - let(:deploy_key) { create(:deploy_key, user: user, can_push: true) } + let(:deploy_key) { create(:deploy_key, user: user) } let(:actor) { deploy_key } context 'when the DeployKey has access to the project' do before do - deploy_key.projects << project + deploy_key.deploy_keys_projects.create(project: project, can_push: true) end it 'allows push and pull access' do @@ -656,15 +656,13 @@ describe Gitlab::GitAccess do end describe 'deploy key permissions' do - let(:key) { create(:deploy_key, user: user, can_push: can_push) } + let(:key) { create(:deploy_key, user: user) } let(:actor) { key } context 'when deploy_key can push' do - let(:can_push) { true } - context 'when project is authorized' do before do - key.projects << project + key.deploy_keys_projects.create(project: project, can_push: true) end it { expect { push_access_check }.not_to raise_error } @@ -692,11 +690,9 @@ describe Gitlab::GitAccess do end context 'when deploy_key cannot push' do - let(:can_push) { false } - context 'when project is authorized' do before do - key.projects << project + key.deploy_keys_projects.create(project: project, can_push: false) end it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:deploy_key_upload]) } diff --git a/spec/models/deploy_keys_project_spec.rb b/spec/models/deploy_keys_project_spec.rb index 0345fefb254..fca3090ff4a 100644 --- a/spec/models/deploy_keys_project_spec.rb +++ b/spec/models/deploy_keys_project_spec.rb @@ -8,7 +8,7 @@ describe DeployKeysProject do describe "Validation" do it { is_expected.to validate_presence_of(:project_id) } - it { is_expected.to validate_presence_of(:deploy_key_id) } + it { is_expected.to validate_presence_of(:deploy_key) } end describe "Destroying" do diff --git a/spec/requests/api/deploy_keys_spec.rb b/spec/requests/api/deploy_keys_spec.rb index 684877c33c0..8e8274ebcbf 100644 --- a/spec/requests/api/deploy_keys_spec.rb +++ b/spec/requests/api/deploy_keys_spec.rb @@ -110,7 +110,7 @@ describe API::DeployKeys do end it 'accepts can_push parameter' do - key_attrs = attributes_for :write_access_key + key_attrs = attributes_for(:another_key).merge(can_push: true) post api("/projects/#{project.id}/deploy_keys", admin), key_attrs @@ -160,16 +160,6 @@ describe API::DeployKeys do expect(json_response['title']).to eq('new title') expect(json_response['can_push']).to eq(true) end - - it 'updates a private ssh key from projects user has access with correct attributes' do - create(:deploy_keys_project, project: project2, deploy_key: private_deploy_key) - - put api("/projects/#{project.id}/deploy_keys/#{private_deploy_key.id}", admin), { title: 'new title', can_push: true } - - expect(json_response['id']).to eq(private_deploy_key.id) - expect(json_response['title']).to eq('new title') - expect(json_response['can_push']).to eq(true) - end end describe 'DELETE /projects/:id/deploy_keys/:key_id' do diff --git a/spec/requests/api/v3/deploy_keys_spec.rb b/spec/requests/api/v3/deploy_keys_spec.rb index 2affd0cfa51..1210e444229 100644 --- a/spec/requests/api/v3/deploy_keys_spec.rb +++ b/spec/requests/api/v3/deploy_keys_spec.rb @@ -107,7 +107,7 @@ describe API::V3::DeployKeys do end it 'accepts can_push parameter' do - key_attrs = attributes_for :write_access_key + key_attrs = attributes_for(:another_key).merge(can_push: true) post v3_api("/projects/#{project.id}/#{path}", admin), key_attrs diff --git a/spec/serializers/deploy_key_entity_spec.rb b/spec/serializers/deploy_key_entity_spec.rb index d3aefa2c9eb..2bd8162d1b7 100644 --- a/spec/serializers/deploy_key_entity_spec.rb +++ b/spec/serializers/deploy_key_entity_spec.rb @@ -21,18 +21,21 @@ describe DeployKeyEntity do user_id: deploy_key.user_id, title: deploy_key.title, fingerprint: deploy_key.fingerprint, - can_push: deploy_key.can_push, destroyed_when_orphaned: true, almost_orphaned: false, created_at: deploy_key.created_at, updated_at: deploy_key.updated_at, can_edit: false, - projects: [ + deploy_keys_projects: [ { - id: project.id, - name: project.name, - full_path: project_path(project), - full_name: project.full_name + can_push: false, + project: + { + id: project.id, + name: project.name, + full_path: project_path(project), + full_name: project.full_name + } } ] } -- GitLab From 62d41f9229f0e2b729274af11020634d45dc90a0 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 8 Jan 2018 15:42:22 +0000 Subject: [PATCH 143/149] Merge branch 'fix/import-rce-10-1' into 'security-10-1' [10.1] Fix RCE via project import mechanism See merge request gitlab/gitlabhq!2292 (cherry picked from commit 9a399c554268f3ac9e9cd2340600c2df2f5dfa47) fdbd8d03 Fix RCE via project import mechanism --- changelogs/unreleased/fix-import-rce.yml | 5 ++ lib/gitlab/import_export/file_importer.rb | 6 +- lib/gitlab/import_export/saver.rb | 2 +- lib/gitlab/import_export/shared.rb | 14 ++++- .../import_export/file_importer_spec.rb | 57 ++++++++++++++----- 5 files changed, 68 insertions(+), 16 deletions(-) create mode 100644 changelogs/unreleased/fix-import-rce.yml diff --git a/changelogs/unreleased/fix-import-rce.yml b/changelogs/unreleased/fix-import-rce.yml new file mode 100644 index 00000000000..c47e45fac31 --- /dev/null +++ b/changelogs/unreleased/fix-import-rce.yml @@ -0,0 +1,5 @@ +--- +title: Fix RCE via project import mechanism +merge_request: +author: +type: security diff --git a/lib/gitlab/import_export/file_importer.rb b/lib/gitlab/import_export/file_importer.rb index 989342389bc..5c971564a73 100644 --- a/lib/gitlab/import_export/file_importer.rb +++ b/lib/gitlab/import_export/file_importer.rb @@ -17,12 +17,16 @@ module Gitlab def import mkdir_p(@shared.export_path) + remove_symlinks! + wait_for_archived_file do decompress_archive end rescue => e @shared.error(e) false + ensure + remove_symlinks! end private @@ -43,7 +47,7 @@ module Gitlab raise Projects::ImportService::Error.new("Unable to decompress #{@archive_file} into #{@shared.export_path}") unless result - remove_symlinks! + result end def remove_symlinks! diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb index 6130c124dd1..2daeba90a51 100644 --- a/lib/gitlab/import_export/saver.rb +++ b/lib/gitlab/import_export/saver.rb @@ -37,7 +37,7 @@ module Gitlab end def archive_file - @archive_file ||= File.join(@shared.export_path, '..', Gitlab::ImportExport.export_filename(project: @project)) + @archive_file ||= File.join(@shared.archive_path, Gitlab::ImportExport.export_filename(project: @project)) end end end diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb index 9fd0b709ef2..d03cbc880fd 100644 --- a/lib/gitlab/import_export/shared.rb +++ b/lib/gitlab/import_export/shared.rb @@ -9,7 +9,11 @@ module Gitlab end def export_path - @export_path ||= Gitlab::ImportExport.export_path(relative_path: opts[:relative_path]) + @export_path ||= Gitlab::ImportExport.export_path(relative_path: relative_path) + end + + def archive_path + @archive_path ||= Gitlab::ImportExport.export_path(relative_path: relative_archive_path) end def error(error) @@ -21,6 +25,14 @@ module Gitlab private + def relative_path + File.join(opts[:relative_path], SecureRandom.hex) + end + + def relative_archive_path + File.join(opts[:relative_path], '..') + end + def error_out(message, caller) Rails.logger.error("Import/Export error raised on #{caller}: #{message}") end diff --git a/spec/lib/gitlab/import_export/file_importer_spec.rb b/spec/lib/gitlab/import_export/file_importer_spec.rb index 162b776e107..5cdc5138fda 100644 --- a/spec/lib/gitlab/import_export/file_importer_spec.rb +++ b/spec/lib/gitlab/import_export/file_importer_spec.rb @@ -12,30 +12,61 @@ describe Gitlab::ImportExport::FileImporter do stub_const('Gitlab::ImportExport::FileImporter::MAX_RETRIES', 0) allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) allow_any_instance_of(Gitlab::ImportExport::CommandLineUtil).to receive(:untar_zxf).and_return(true) - + allow(SecureRandom).to receive(:hex).and_return('abcd') setup_files - - described_class.import(archive_file: '', shared: shared) end after do FileUtils.rm_rf(export_path) end - it 'removes symlinks in root folder' do - expect(File.exist?(symlink_file)).to be false - end + context 'normal run' do + before do + described_class.import(archive_file: '', shared: shared) + end - it 'removes hidden symlinks in root folder' do - expect(File.exist?(hidden_symlink_file)).to be false - end + it 'removes symlinks in root folder' do + expect(File.exist?(symlink_file)).to be false + end + + it 'removes hidden symlinks in root folder' do + expect(File.exist?(hidden_symlink_file)).to be false + end + + it 'removes symlinks in subfolders' do + expect(File.exist?(subfolder_symlink_file)).to be false + end - it 'removes symlinks in subfolders' do - expect(File.exist?(subfolder_symlink_file)).to be false + it 'does not remove a valid file' do + expect(File.exist?(valid_file)).to be true + end + + it 'creates the file in the right subfolder' do + expect(shared.export_path).to include('test/abcd') + end end - it 'does not remove a valid file' do - expect(File.exist?(valid_file)).to be true + context 'error' do + before do + allow_any_instance_of(described_class).to receive(:wait_for_archived_file).and_raise(StandardError) + described_class.import(archive_file: '', shared: shared) + end + + it 'removes symlinks in root folder' do + expect(File.exist?(symlink_file)).to be false + end + + it 'removes hidden symlinks in root folder' do + expect(File.exist?(hidden_symlink_file)).to be false + end + + it 'removes symlinks in subfolders' do + expect(File.exist?(subfolder_symlink_file)).to be false + end + + it 'does not remove a valid file' do + expect(File.exist?(valid_file)).to be true + end end def setup_files -- GitLab From fd2813650b3e9b8b85596b8640fbf2bdc7496dfa Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 8 Jan 2018 17:51:00 +0000 Subject: [PATCH 144/149] Merge branch '41293-fix-command-injection-vulnerability-on-system_hook_push-queue-through-web-hook-10-1' into 'security-10-1' [10.1] Don't allow line breaks on HTTP headers See merge request gitlab/gitlabhq!2286 (cherry picked from commit 271ef222fa964481379a14a9c07805621a7d52a6) a30812d3 Don't allow line breaks on HTTP headers --- app/models/hooks/web_hook.rb | 1 + app/services/web_hook_service.rb | 2 +- lib/gitlab/utils.rb | 4 ++++ spec/lib/gitlab/utils_spec.rb | 16 ++++++++++++++++ spec/models/hooks/web_hook_spec.rb | 6 ++++++ 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index 5a70e114f56..27729deeac9 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -4,6 +4,7 @@ class WebHook < ActiveRecord::Base has_many :web_hook_logs, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent validates :url, presence: true, url: true + validates :token, format: { without: /\n/ } def execute(data, hook_name) WebHookService.new(self, data, hook_name).execute diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb index cd99e0b90f9..a3c90e4f908 100644 --- a/app/services/web_hook_service.rb +++ b/app/services/web_hook_service.rb @@ -113,7 +113,7 @@ class WebHookService 'Content-Type' => 'application/json', 'X-Gitlab-Event' => hook_name.singularize.titleize }.tap do |hash| - hash['X-Gitlab-Token'] = hook.token if hook.token.present? + hash['X-Gitlab-Token'] = Gitlab::Utils.remove_line_breaks(hook.token) if hook.token.present? end end end diff --git a/lib/gitlab/utils.rb b/lib/gitlab/utils.rb index abb3d3a02c3..3cb113373d2 100644 --- a/lib/gitlab/utils.rb +++ b/lib/gitlab/utils.rb @@ -27,6 +27,10 @@ module Gitlab .gsub(/(\A-+|-+\z)/, '') end + def remove_line_breaks(str) + str.gsub(/\r?\n/, '') + end + def to_boolean(value) return value if [true, false].include?(value) return true if value =~ /^(true|t|yes|y|1|on)$/i diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb index 3137a72fdc4..d6eea28d53e 100644 --- a/spec/lib/gitlab/utils_spec.rb +++ b/spec/lib/gitlab/utils_spec.rb @@ -17,6 +17,22 @@ describe Gitlab::Utils do end end + describe '.remove_line_breaks' do + using RSpec::Parameterized::TableSyntax + + where(:original, :expected) do + "foo\nbar\nbaz" | "foobarbaz" + "foo\r\nbar\r\nbaz" | "foobarbaz" + "foobar" | "foobar" + end + + with_them do + it "replace line breaks with an empty string" do + expect(described_class.remove_line_breaks(original)).to eq(expected) + end + end + end + describe '.to_boolean' do it 'accepts booleans' do expect(to_boolean(true)).to be(true) diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb index 388120160ab..ea6d6e53ef5 100644 --- a/spec/models/hooks/web_hook_spec.rb +++ b/spec/models/hooks/web_hook_spec.rb @@ -29,6 +29,12 @@ describe WebHook do expect(hook.url).to eq('https://example.com') end end + + describe 'token' do + it { is_expected.to allow_value("foobar").for(:token) } + + it { is_expected.not_to allow_values("foo\nbar", "foo\r\nbar").for(:token) } + end end describe 'execute' do -- GitLab From ecb69c3f5e345f5762b2ace3e38c9388cf54e694 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 9 Jan 2018 08:38:43 +0000 Subject: [PATCH 145/149] Merge branch 'fl-ipython' into 'security-10-1' Port of [10.2] Sanitizes IPython notebook output See merge request gitlab/gitlabhq!2284 (cherry picked from commit 72ce40bdebe73a06dc282d42f2c8a729730c9cee) 989d1187 Port of [10.2] Sanitizes IPython notebook output --- .../javascripts/notebook/cells/markdown.vue | 8 +- .../notebook/cells/output/html.vue | 15 +++- package.json | 1 + .../notebook/cells/markdown_spec.js | 12 +++ .../cells/output/html_sanitize_tests.js | 66 ++++++++++++++++ .../notebook/cells/output/html_spec.js | 29 +++++++ yarn.lock | 79 ++++++++++++++++++- 7 files changed, 206 insertions(+), 4 deletions(-) create mode 100644 spec/javascripts/notebook/cells/output/html_sanitize_tests.js create mode 100644 spec/javascripts/notebook/cells/output/html_spec.js diff --git a/app/assets/javascripts/notebook/cells/markdown.vue b/app/assets/javascripts/notebook/cells/markdown.vue index 82c51a1068c..721753af595 100644 --- a/app/assets/javascripts/notebook/cells/markdown.vue +++ b/app/assets/javascripts/notebook/cells/markdown.vue @@ -1,6 +1,7 @@ diff --git a/package.json b/package.json index 5aa3ce3f757..36be7105e49 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "raven-js": "^3.14.0", "raw-loader": "^0.5.1", "react-dev-utils": "^0.5.2", + "sanitize-html": "^1.16.1", "select2": "3.5.2-browserify", "sql.js": "^0.4.0", "svg4everybody": "2.1.9", diff --git a/spec/javascripts/notebook/cells/markdown_spec.js b/spec/javascripts/notebook/cells/markdown_spec.js index a88e9ed3d99..db2a16b0b68 100644 --- a/spec/javascripts/notebook/cells/markdown_spec.js +++ b/spec/javascripts/notebook/cells/markdown_spec.js @@ -42,6 +42,18 @@ describe('Markdown component', () => { expect(vm.$el.querySelector('.markdown h1')).not.toBeNull(); }); + it('sanitizes output', (done) => { + Object.assign(cell, { + source: ['[XSS](data:text/html;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pPC9zY3JpcHQ+Cg==)\n'], + }); + + Vue.nextTick(() => { + expect(vm.$el.querySelector('a').getAttribute('href')).toBeNull(); + + done(); + }); + }); + describe('katex', () => { beforeEach(() => { json = getJSONFixture('blob/notebook/math.json'); diff --git a/spec/javascripts/notebook/cells/output/html_sanitize_tests.js b/spec/javascripts/notebook/cells/output/html_sanitize_tests.js new file mode 100644 index 00000000000..d587573fc9e --- /dev/null +++ b/spec/javascripts/notebook/cells/output/html_sanitize_tests.js @@ -0,0 +1,66 @@ +export default { + 'protocol-based JS injection: simple, no spaces': { + input: 'foo', + output: 'foo', + }, + 'protocol-based JS injection: simple, spaces before': { + input: 'foo', + output: 'foo', + }, + 'protocol-based JS injection: simple, spaces after': { + input: 'foo', + output: 'foo', + }, + 'protocol-based JS injection: simple, spaces before and after': { + input: 'foo', + output: 'foo', + }, + 'protocol-based JS injection: preceding colon': { + input: 'foo', + output: 'foo', + }, + 'protocol-based JS injection: UTF-8 encoding': { + input: 'foo', + output: 'foo', + }, + 'protocol-based JS injection: long UTF-8 encoding': { + input: 'foo', + output: 'foo', + }, + 'protocol-based JS injection: long UTF-8 encoding without semicolons': { + input: 'foo', + output: 'foo', + }, + 'protocol-based JS injection: hex encoding': { + input: 'foo', + output: 'foo', + }, + 'protocol-based JS injection: long hex encoding': { + input: 'foo', + output: 'foo', + }, + 'protocol-based JS injection: hex encoding without semicolons': { + input: 'foo', + output: 'foo', + }, + 'protocol-based JS injection: null char': { + input: 'foo', + output: 'foo', + }, + 'protocol-based JS injection: invalid URL char': { + input: '', // eslint-disable-line no-useless-escape + output: '', + }, + 'protocol-based JS injection: Unicode': { + input: 'foo', + output: 'foo', + }, + 'protocol-based JS injection: spaces and entities': { + input: 'foo', + output: 'foo', + }, + 'img on error': { + input: '', + output: '', + }, +}; diff --git a/spec/javascripts/notebook/cells/output/html_spec.js b/spec/javascripts/notebook/cells/output/html_spec.js new file mode 100644 index 00000000000..9c5385f2922 --- /dev/null +++ b/spec/javascripts/notebook/cells/output/html_spec.js @@ -0,0 +1,29 @@ +import Vue from 'vue'; +import htmlOutput from '~/notebook/cells/output/html.vue'; +import sanitizeTests from './html_sanitize_tests'; + +describe('html output cell', () => { + function createComponent(rawCode) { + const Component = Vue.extend(htmlOutput); + + return new Component({ + propsData: { + rawCode, + }, + }).$mount(); + } + + describe('sanitizes output', () => { + Object.keys(sanitizeTests).forEach((key) => { + it(key, () => { + const test = sanitizeTests[key]; + const vm = createComponent(test.input); + const outputEl = [...vm.$el.querySelectorAll('div')].pop(); + + expect(outputEl.innerHTML).toEqual(test.output); + + vm.$destroy(); + }); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index 57644482b32..e6e19d89b36 100644 --- a/yarn.lock +++ b/yarn.lock @@ -101,6 +101,12 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" +ansi-styles@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + dependencies: + color-convert "^1.9.0" + anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" @@ -167,7 +173,7 @@ array-union@^1.0.1: dependencies: array-uniq "^1.0.1" -array-uniq@^1.0.1: +array-uniq@^1.0.1, array-uniq@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" @@ -1166,6 +1172,14 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.6.0, chokidar@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" @@ -1255,6 +1269,12 @@ color-convert@^1.3.0: dependencies: color-name "^1.1.1" +color-convert@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + dependencies: + color-name "^1.1.1" + color-name@^1.0.0, color-name@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.2.tgz#5c8ab72b64bd2215d617ae9559ebb148475cf98d" @@ -2978,7 +2998,7 @@ html-entities@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" -htmlparser2@^3.8.2: +htmlparser2@^3.8.2, htmlparser2@^3.9.0: version "3.9.2" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" dependencies: @@ -3858,6 +3878,10 @@ lodash.capitalize@^4.0.0: version "4.2.1" resolved "https://registry.yarnpkg.com/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz#f826c9b4e2a8511d84e3aca29db05e1a4f3b72a9" +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + lodash.cond@^4.3.0: version "4.5.2" resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" @@ -3873,6 +3897,10 @@ lodash.defaults@^3.1.2: lodash.assign "^3.0.0" lodash.restparam "^3.0.0" +lodash.escaperegexp@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" + lodash.get@4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" @@ -3911,6 +3939,10 @@ lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" +lodash.mergewith@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" + lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" @@ -4984,6 +5016,14 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0 source-map "^0.5.6" supports-color "^3.2.3" +postcss@^6.0.14: + version "6.0.15" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.15.tgz#f460cd6269fede0d1bf6defff0b934a9845d974d" + dependencies: + chalk "^2.3.0" + source-map "^0.6.1" + supports-color "^5.1.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -5492,6 +5532,18 @@ safe-buffer@^5.0.1, safe-buffer@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" +sanitize-html@^1.16.1: + version "1.16.3" + resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.16.3.tgz#96c1b44a36ff7312e1c22a14b05274370ac8bd56" + dependencies: + htmlparser2 "^3.9.0" + lodash.clonedeep "^4.5.0" + lodash.escaperegexp "^4.1.2" + lodash.mergewith "^4.6.0" + postcss "^6.0.14" + srcset "^1.0.0" + xtend "^4.0.0" + sax@~1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.2.tgz#fd8631a23bc7826bef5d871bdb87378c95647828" @@ -5746,6 +5798,10 @@ source-map@^0.4.4: dependencies: amdefine ">=0.0.4" +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" @@ -5803,6 +5859,13 @@ sql.js@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/sql.js/-/sql.js-0.4.0.tgz#23be9635520eb0ff43a741e7e830397266e88445" +srcset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/srcset/-/srcset-1.0.0.tgz#a5669de12b42f3b1d5e83ed03c71046fc48f41ef" + dependencies: + array-uniq "^1.0.2" + number-is-nan "^1.0.0" + sshpk@^1.7.0: version "1.13.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" @@ -5935,12 +5998,24 @@ supports-color@^3.1.0, supports-color@^3.1.1, supports-color@^3.1.2, supports-co dependencies: has-flag "^1.0.0" +supports-color@^4.0.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + dependencies: + has-flag "^2.0.0" + supports-color@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.1.tgz#65a4bb2631e90e02420dba5554c375a4754bb836" dependencies: has-flag "^2.0.0" +supports-color@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.1.0.tgz#058a021d1b619f7ddf3980d712ea3590ce7de3d5" + dependencies: + has-flag "^2.0.0" + svg4everybody@2.1.9: version "2.1.9" resolved "https://registry.yarnpkg.com/svg4everybody/-/svg4everybody-2.1.9.tgz#5bd9f6defc133859a044646d4743fabc28db7e2d" -- GitLab From af2b12617449f4154cea614d0d0586e95b997b56 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 14 Dec 2017 18:10:05 +0000 Subject: [PATCH 146/149] Merge branch 'jej/fix-disabled-oauth-access-10-1' into 'security-10-1' [10.1] Prevent login with disabled OAuth providers See merge request gitlab/gitlabhq!2249 (cherry picked from commit e4951cc45f29a9ec1e07408102ab339444ff43e8) 71d8d00c Prevents login with disabled OAuth providers --- .../omniauth_callbacks_controller.rb | 9 +++ .../jej-fix-disabled-oauth-access.yml | 5 ++ lib/gitlab/o_auth.rb | 6 ++ lib/gitlab/o_auth/user.rb | 11 +-- .../omniauth_callbacks_controller_spec.rb | 75 +++++++++++++++++++ spec/features/oauth_login_spec.rb | 3 +- spec/support/devise_helpers.rb | 15 ++-- spec/support/login_helpers.rb | 7 ++ 8 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 changelogs/unreleased/jej-fix-disabled-oauth-access.yml create mode 100644 lib/gitlab/o_auth.rb create mode 100644 spec/controllers/omniauth_callbacks_controller_spec.rb diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index 9612b8d8514..b87348fe4e6 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -108,6 +108,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController continue_login_process end + rescue Gitlab::OAuth::SigninDisabledForProviderError + handle_disabled_provider rescue Gitlab::OAuth::SignupDisabledError handle_signup_error end @@ -163,6 +165,13 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController redirect_to new_user_session_path end + def handle_disabled_provider + label = Gitlab::OAuth::Provider.label_for(oauth['provider']) + flash[:alert] = "Signing in using #{label} has been disabled" + + redirect_to new_user_session_path + end + def log_audit_event(user, options = {}) AuditEventService.new(user, user, options) .for_authentication.security_event diff --git a/changelogs/unreleased/jej-fix-disabled-oauth-access.yml b/changelogs/unreleased/jej-fix-disabled-oauth-access.yml new file mode 100644 index 00000000000..3a92c432dc6 --- /dev/null +++ b/changelogs/unreleased/jej-fix-disabled-oauth-access.yml @@ -0,0 +1,5 @@ +--- +title: Prevent OAuth login POST requests when a provider has been disabled +merge_request: +author: +type: security diff --git a/lib/gitlab/o_auth.rb b/lib/gitlab/o_auth.rb new file mode 100644 index 00000000000..5ad8d83bd6e --- /dev/null +++ b/lib/gitlab/o_auth.rb @@ -0,0 +1,6 @@ +module Gitlab + module OAuth + SignupDisabledError = Class.new(StandardError) + SigninDisabledForProviderError = Class.new(StandardError) + end +end diff --git a/lib/gitlab/o_auth/user.rb b/lib/gitlab/o_auth/user.rb index 47c2a422387..498c542862f 100644 --- a/lib/gitlab/o_auth/user.rb +++ b/lib/gitlab/o_auth/user.rb @@ -5,8 +5,6 @@ # module Gitlab module OAuth - SignupDisabledError = Class.new(StandardError) - class User attr_accessor :auth_hash, :gl_user @@ -29,7 +27,8 @@ module Gitlab end def save(provider = 'OAuth') - unauthorized_to_create unless gl_user + raise SigninDisabledForProviderError if oauth_provider_disabled? + raise SignupDisabledError unless gl_user block_after_save = needs_blocking? @@ -224,8 +223,10 @@ module Gitlab Gitlab::AppLogger end - def unauthorized_to_create - raise SignupDisabledError + def oauth_provider_disabled? + Gitlab::CurrentSettings.current_application_settings + .disabled_oauth_sign_in_sources + .include?(auth_hash.provider) end end end diff --git a/spec/controllers/omniauth_callbacks_controller_spec.rb b/spec/controllers/omniauth_callbacks_controller_spec.rb new file mode 100644 index 00000000000..c639ad32ec6 --- /dev/null +++ b/spec/controllers/omniauth_callbacks_controller_spec.rb @@ -0,0 +1,75 @@ +require 'spec_helper' + +describe OmniauthCallbacksController do + include LoginHelpers + + let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: provider) } + let(:provider) { :github } + + before do + mock_auth_hash(provider.to_s, 'my-uid', user.email) + stub_omniauth_provider(provider, context: request) + end + + it 'allows sign in' do + post provider + + expect(request.env['warden']).to be_authenticated + end + + shared_context 'sign_up' do + let(:user) { double(email: 'new@example.com') } + + before do + stub_omniauth_setting(block_auto_created_users: false) + end + end + + context 'sign up' do + include_context 'sign_up' + + it 'is allowed' do + post provider + + expect(request.env['warden']).to be_authenticated + end + end + + context 'when OAuth is disabled' do + before do + stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') + settings = Gitlab::CurrentSettings.current_application_settings + settings.update(disabled_oauth_sign_in_sources: [provider.to_s]) + end + + it 'prevents login via POST' do + post provider + + expect(request.env['warden']).not_to be_authenticated + end + + it 'shows warning when attempting login' do + post provider + + expect(response).to redirect_to new_user_session_path + expect(flash[:alert]).to eq('Signing in using GitHub has been disabled') + end + + it 'allows linking the disabled provider' do + user.identities.destroy_all + sign_in(user) + + expect { post provider }.to change { user.reload.identities.count }.by(1) + end + + context 'sign up' do + include_context 'sign_up' + + it 'is prevented' do + post provider + + expect(request.env['warden']).not_to be_authenticated + end + end + end +end diff --git a/spec/features/oauth_login_spec.rb b/spec/features/oauth_login_spec.rb index 49d8e52f861..a5e325ee2e3 100644 --- a/spec/features/oauth_login_spec.rb +++ b/spec/features/oauth_login_spec.rb @@ -10,8 +10,7 @@ feature 'OAuth Login', :js, :allow_forgery_protection do def stub_omniauth_config(provider) OmniAuth.config.add_mock(provider, OmniAuth::AuthHash.new(provider: provider.to_s, uid: "12345")) - set_devise_mapping(context: Rails.application) - Rails.application.env_config['omniauth.auth'] = OmniAuth.config.mock_auth[provider] + stub_omniauth_provider(provider) end providers = [:github, :twitter, :bitbucket, :gitlab, :google_oauth2, diff --git a/spec/support/devise_helpers.rb b/spec/support/devise_helpers.rb index 890a2d9d287..66874e10f38 100644 --- a/spec/support/devise_helpers.rb +++ b/spec/support/devise_helpers.rb @@ -2,13 +2,16 @@ module DeviseHelpers # explicitly tells Devise which mapping to use # this is needed when we are testing a Devise controller bypassing the router def set_devise_mapping(context:) - env = - if context.respond_to?(:env_config) - context.env_config - elsif context.respond_to?(:env) - context.env - end + env = env_from_context(context) env['devise.mapping'] = Devise.mappings[:user] if env end + + def env_from_context(context) + if context.respond_to?(:env_config) + context.env_config + elsif context.respond_to?(:env) + context.env + end + end end diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb index 3e117530151..e821e20a432 100644 --- a/spec/support/login_helpers.rb +++ b/spec/support/login_helpers.rb @@ -109,6 +109,13 @@ module LoginHelpers }) end + def stub_omniauth_provider(provider, context: Rails.application) + env = env_from_context(context) + + set_devise_mapping(context: context) + env['omniauth.auth'] = OmniAuth.config.mock_auth[provider] + end + def stub_omniauth_saml_config(messages) set_devise_mapping(context: Rails.application) Rails.application.routes.disable_clear_and_finalize = true -- GitLab From 6926edd0af67bd5d643118978abb036de6632d8d Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Thu, 11 Jan 2018 14:23:41 -0200 Subject: [PATCH 147/149] Update CHANGELOG.md for 10.1.6 [ci skip] --- CHANGELOG.md | 14 ++++++++++++++ .../unreleased/ac-41346-xss-ci-job-output.yml | 5 ----- changelogs/unreleased/api-no-service-pw-output.yml | 5 ----- changelogs/unreleased/fix-import-rce.yml | 5 ----- .../unreleased/jej-fix-disabled-oauth-access.yml | 5 ----- .../unreleased/milestones-finder-order-fix.yml | 5 ----- changelogs/unreleased/projectfix.yml | 6 ------ changelogs/unreleased/security-10-3.yml | 5 ----- ...sh-migrate-can-push-to-deploy-keys-projects.yml | 5 ----- 9 files changed, 14 insertions(+), 41 deletions(-) delete mode 100644 changelogs/unreleased/ac-41346-xss-ci-job-output.yml delete mode 100644 changelogs/unreleased/api-no-service-pw-output.yml delete mode 100644 changelogs/unreleased/fix-import-rce.yml delete mode 100644 changelogs/unreleased/jej-fix-disabled-oauth-access.yml delete mode 100644 changelogs/unreleased/milestones-finder-order-fix.yml delete mode 100644 changelogs/unreleased/projectfix.yml delete mode 100644 changelogs/unreleased/security-10-3.yml delete mode 100644 changelogs/unreleased/sh-migrate-can-push-to-deploy-keys-projects.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index a2015f42a10..d174f6e70b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 10.1.6 (2018-01-11) + +### Security (8 changes, 1 of them is from the community) + +- Fix writable shared deploy keys. +- Filter out sensitive fields from the project services API. (Robert Schilling) +- Fix RCE via project import mechanism. +- Prevent OAuth login POST requests when a provider has been disabled. +- Prevent a SQL injection in the MilestonesFinder. +- Check user authorization for source and target projects when creating a merge request. +- Fix path traversal in gitlab-ci.yml cache:key. +- Fix XSS vulnerability in pipeline job trace. + + ## 10.1.5 (2017-12-07) ### Security (5 changes) diff --git a/changelogs/unreleased/ac-41346-xss-ci-job-output.yml b/changelogs/unreleased/ac-41346-xss-ci-job-output.yml deleted file mode 100644 index 5ef42e49b71..00000000000 --- a/changelogs/unreleased/ac-41346-xss-ci-job-output.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix XSS vulnerability in pipeline job trace -merge_request: -author: -type: security diff --git a/changelogs/unreleased/api-no-service-pw-output.yml b/changelogs/unreleased/api-no-service-pw-output.yml deleted file mode 100644 index f0d0adaad1c..00000000000 --- a/changelogs/unreleased/api-no-service-pw-output.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Filter out sensitive fields from the project services API -merge_request: -author: Robert Schilling -type: security diff --git a/changelogs/unreleased/fix-import-rce.yml b/changelogs/unreleased/fix-import-rce.yml deleted file mode 100644 index c47e45fac31..00000000000 --- a/changelogs/unreleased/fix-import-rce.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix RCE via project import mechanism -merge_request: -author: -type: security diff --git a/changelogs/unreleased/jej-fix-disabled-oauth-access.yml b/changelogs/unreleased/jej-fix-disabled-oauth-access.yml deleted file mode 100644 index 3a92c432dc6..00000000000 --- a/changelogs/unreleased/jej-fix-disabled-oauth-access.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Prevent OAuth login POST requests when a provider has been disabled -merge_request: -author: -type: security diff --git a/changelogs/unreleased/milestones-finder-order-fix.yml b/changelogs/unreleased/milestones-finder-order-fix.yml deleted file mode 100644 index 983c301a82d..00000000000 --- a/changelogs/unreleased/milestones-finder-order-fix.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Prevent a SQL injection in the MilestonesFinder -merge_request: -author: -type: security diff --git a/changelogs/unreleased/projectfix.yml b/changelogs/unreleased/projectfix.yml deleted file mode 100644 index 4d8ebe6194a..00000000000 --- a/changelogs/unreleased/projectfix.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Check user authorization for source and target projects when creating a merge - request. -merge_request: -author: -type: security diff --git a/changelogs/unreleased/security-10-3.yml b/changelogs/unreleased/security-10-3.yml deleted file mode 100644 index 5c718d976cd..00000000000 --- a/changelogs/unreleased/security-10-3.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix path traversal in gitlab-ci.yml cache:key -merge_request: -author: -type: security diff --git a/changelogs/unreleased/sh-migrate-can-push-to-deploy-keys-projects.yml b/changelogs/unreleased/sh-migrate-can-push-to-deploy-keys-projects.yml deleted file mode 100644 index cb53a94e465..00000000000 --- a/changelogs/unreleased/sh-migrate-can-push-to-deploy-keys-projects.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix writable shared deploy keys -merge_request: -author: -type: security -- GitLab From c3f66154d76aaf3653e67418f2a93f8dfc293004 Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Thu, 11 Jan 2018 14:23:59 -0200 Subject: [PATCH 148/149] Update VERSION to 10.1.6 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 655f923d60d..08f86164395 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -10.1.4 +10.1.6 -- GitLab From 7c9b98273bf2a63eaae37d72a4ec1b641ad425a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Javier=20L=C3=B3pez?= Date: Wed, 17 Jan 2018 21:57:12 +0000 Subject: [PATCH 149/149] [10.1] Fix bug in security release with deploy keys migration --- ...late_can_push_from_deploy_keys_projects.rb | 48 +++++++++++++------ ...late_can_push_from_deploy_keys_projects.rb | 48 +++++++++++++------ ...can_push_from_deploy_keys_projects_spec.rb | 43 +++++++++++++++++ 3 files changed, 111 insertions(+), 28 deletions(-) create mode 100644 spec/migrations/populate_can_push_from_deploy_keys_projects_spec.rb diff --git a/db/migrate/20171215113714_populate_can_push_from_deploy_keys_projects.rb b/db/migrate/20171215113714_populate_can_push_from_deploy_keys_projects.rb index ec0427a8e5a..680855af945 100644 --- a/db/migrate/20171215113714_populate_can_push_from_deploy_keys_projects.rb +++ b/db/migrate/20171215113714_populate_can_push_from_deploy_keys_projects.rb @@ -6,6 +6,8 @@ class PopulateCanPushFromDeployKeysProjects < ActiveRecord::Migration # Set this constant to true if this migration requires downtime. DOWNTIME = false + DATABASE_NAME = Gitlab::Database.database_name + disable_ddl_transaction! class DeploysKeyProject < ActiveRecord::Base @@ -18,13 +20,22 @@ class PopulateCanPushFromDeployKeysProjects < ActiveRecord::Migration DeploysKeyProject.each_batch(of: 10_000) do |batch| start_id, end_id = batch.pluck('MIN(id), MAX(id)').first - execute <<-EOF - UPDATE deploy_keys_projects - SET can_push = keys.can_push - FROM keys - WHERE deploy_key_id = keys.id - AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} - EOF + if Gitlab::Database.mysql? + execute <<-EOF.strip_heredoc + UPDATE deploy_keys_projects, #{DATABASE_NAME}.keys + SET deploy_keys_projects.can_push = #{DATABASE_NAME}.keys.can_push + WHERE deploy_keys_projects.deploy_key_id = #{DATABASE_NAME}.keys.id + AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} + EOF + else + execute <<-EOF.strip_heredoc + UPDATE deploy_keys_projects + SET can_push = keys.can_push + FROM keys + WHERE deploy_key_id = keys.id + AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} + EOF + end end end @@ -32,13 +43,22 @@ class PopulateCanPushFromDeployKeysProjects < ActiveRecord::Migration DeploysKeyProject.each_batch(of: 10_000) do |batch| start_id, end_id = batch.pluck('MIN(id), MAX(id)').first - execute <<-EOF - UPDATE keys - SET can_push = deploy_keys_projects.can_push - FROM deploy_keys_projects - WHERE deploy_keys_projects.deploy_key_id = keys.id - AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} - EOF + if Gitlab::Database.mysql? + execute <<-EOF.strip_heredoc + UPDATE deploy_keys_projects, #{DATABASE_NAME}.keys + SET #{DATABASE_NAME}.keys.can_push = deploy_keys_projects.can_push + WHERE deploy_keys_projects.deploy_key_id = #{DATABASE_NAME}.keys.id + AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} + EOF + else + execute <<-EOF.strip_heredoc + UPDATE keys + SET can_push = deploy_keys_projects.can_push + FROM deploy_keys_projects + WHERE deploy_keys_projects.deploy_key_id = keys.id + AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} + EOF + end end end end diff --git a/db/post_migrate/20171215121205_post_populate_can_push_from_deploy_keys_projects.rb b/db/post_migrate/20171215121205_post_populate_can_push_from_deploy_keys_projects.rb index 05d236f8e96..3a5850df3db 100644 --- a/db/post_migrate/20171215121205_post_populate_can_push_from_deploy_keys_projects.rb +++ b/db/post_migrate/20171215121205_post_populate_can_push_from_deploy_keys_projects.rb @@ -5,6 +5,8 @@ class PostPopulateCanPushFromDeployKeysProjects < ActiveRecord::Migration include Gitlab::Database::MigrationHelpers DOWNTIME = false + DATABASE_NAME = Gitlab::Database.database_name + disable_ddl_transaction! class DeploysKeyProject < ActiveRecord::Base @@ -17,13 +19,22 @@ class PostPopulateCanPushFromDeployKeysProjects < ActiveRecord::Migration DeploysKeyProject.each_batch(of: 10_000) do |batch| start_id, end_id = batch.pluck('MIN(id), MAX(id)').first - execute <<-EOF - UPDATE deploy_keys_projects - SET can_push = keys.can_push - FROM keys - WHERE deploy_key_id = keys.id - AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} - EOF + if Gitlab::Database.mysql? + execute <<-EOF.strip_heredoc + UPDATE deploy_keys_projects, #{DATABASE_NAME}.keys + SET deploy_keys_projects.can_push = #{DATABASE_NAME}.keys.can_push + WHERE deploy_keys_projects.deploy_key_id = #{DATABASE_NAME}.keys.id + AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} + EOF + else + execute <<-EOF.strip_heredoc + UPDATE deploy_keys_projects + SET can_push = keys.can_push + FROM keys + WHERE deploy_key_id = keys.id + AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} + EOF + end end end @@ -31,13 +42,22 @@ class PostPopulateCanPushFromDeployKeysProjects < ActiveRecord::Migration DeploysKeyProject.each_batch(of: 10_000) do |batch| start_id, end_id = batch.pluck('MIN(id), MAX(id)').first - execute <<-EOF - UPDATE keys - SET can_push = deploy_keys_projects.can_push - FROM deploy_keys_projects - WHERE deploy_keys_projects.deploy_key_id = keys.id - AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} - EOF + if Gitlab::Database.mysql? + execute <<-EOF.strip_heredoc + UPDATE deploy_keys_projects, #{DATABASE_NAME}.keys + SET #{DATABASE_NAME}.keys.can_push = deploy_keys_projects.can_push + WHERE deploy_keys_projects.deploy_key_id = #{DATABASE_NAME}.keys.id + AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} + EOF + else + execute <<-EOF.strip_heredoc + UPDATE keys + SET can_push = deploy_keys_projects.can_push + FROM deploy_keys_projects + WHERE deploy_keys_projects.deploy_key_id = keys.id + AND deploy_keys_projects.id BETWEEN #{start_id} AND #{end_id} + EOF + end end end end diff --git a/spec/migrations/populate_can_push_from_deploy_keys_projects_spec.rb b/spec/migrations/populate_can_push_from_deploy_keys_projects_spec.rb new file mode 100644 index 00000000000..0ff98933d5c --- /dev/null +++ b/spec/migrations/populate_can_push_from_deploy_keys_projects_spec.rb @@ -0,0 +1,43 @@ +require 'spec_helper' +require Rails.root.join('db', 'migrate', '20171215113714_populate_can_push_from_deploy_keys_projects.rb') + +describe PopulateCanPushFromDeployKeysProjects, :migration do + let(:migration) { described_class.new } + let(:deploy_keys) { table(:keys) } + let(:deploy_keys_projects) { table(:deploy_keys_projects) } + let(:projects) { table(:projects) } + + before do + deploy_keys.inheritance_column = nil + + projects.create!(id: 1, name: 'gitlab1', path: 'gitlab1') + (1..10).each do |index| + deploy_keys.create!(id: index, title: 'dummy', type: 'DeployKey', key: Spec::Support::Helpers::KeyGeneratorHelper.new(1024).generate + ' dummy@gitlab.com') + deploy_keys_projects.create!(id: index, deploy_key_id: index, project_id: 1) + end + end + + describe '#up' do + it 'migrates can_push from deploy_keys to deploy_keys_projects' do + deploy_keys.limit(5).update_all(can_push: true) + + expected = deploy_keys.order(:id).pluck(:id, :can_push) + + migration.up + + expect(deploy_keys_projects.order(:id).pluck(:deploy_key_id, :can_push)).to eq expected + end + end + + describe '#down' do + it 'migrates can_push from deploy_keys_projects to deploy_keys' do + deploy_keys_projects.limit(5).update_all(can_push: true) + + expected = deploy_keys_projects.order(:id).pluck(:deploy_key_id, :can_push) + + migration.down + + expect(deploy_keys.order(:id).pluck(:id, :can_push)).to eq expected + end + end +end -- GitLab