diff options
Diffstat (limited to 'app')
57 files changed, 228 insertions, 134 deletions
diff --git a/app/assets/javascripts/boards/components/modal/index.js b/app/assets/javascripts/boards/components/modal/index.js index 1b66c8b922d..4240c97617d 100644 --- a/app/assets/javascripts/boards/components/modal/index.js +++ b/app/assets/javascripts/boards/components/modal/index.js @@ -64,6 +64,7 @@ require('./empty_state'); }, filter: { handler() { + this.page = 1; this.loadIssues(true); }, deep: true, @@ -115,6 +116,9 @@ require('./empty_state'); return this.activeTab === 'selected' && this.selectedIssues.length === 0; }, }, + created() { + this.page = 1; + }, components: { 'modal-header': gl.issueBoards.ModalHeader, 'modal-list': gl.issueBoards.ModalList, diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index db1a2848d8d..3557f6f617e 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -1,4 +1,3 @@ -import PrometheusGraph from './monitoring/prometheus_graph'; // TODO: Maybe Make this a bundle /* eslint-disable func-names, space-before-function-paren, no-var, prefer-arrow-callback, wrap-iife, no-shadow, consistent-return, one-var, one-var-declaration-per-line, camelcase, default-case, no-new, quotes, no-duplicate-case, no-case-declarations, no-fallthrough, max-len */ /* global UsernameValidator */ /* global ActiveTabMemoizer */ @@ -329,8 +328,6 @@ const UserCallout = require('./user_callout'); case 'ci:lints:show': new gl.CILintEditor(); break; - case 'projects:environments:metrics': - new PrometheusGraph(); case 'users:show': new UserCallout(); break; diff --git a/app/assets/javascripts/environments/components/environment_external_url.js b/app/assets/javascripts/environments/components/environment_external_url.js index a554998f52c..b4f9eb357fd 100644 --- a/app/assets/javascripts/environments/components/environment_external_url.js +++ b/app/assets/javascripts/environments/components/environment_external_url.js @@ -14,6 +14,7 @@ export default { class="btn external_url" :href="externalUrl" target="_blank" + rel="noopener noreferrer" title="Environment external URL"> <i class="fa fa-external-link" aria-hidden="true"></i> </a> diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js index 134bdc6ad80..e7bf530d343 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js +++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js @@ -38,6 +38,7 @@ gl.FilteredSearchDropdownManager.addWordToInput(this.filter, value, true); } + this.resetFilters(); this.dismissDropdown(); this.dispatchInputEvent(); } @@ -107,7 +108,7 @@ const hook = this.getCurrentHook(); if (hook) { - const data = hook.list.data; + const data = hook.list.data || []; const results = data.map((o) => { const updated = o; updated.droplab_hidden = false; diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js index 7ace51748aa..c6bb7fda8f2 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_manager.js +++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js @@ -40,6 +40,8 @@ import FilteredSearchContainer from './container'; this.unselectEditTokensWrapper = this.unselectEditTokens.bind(this); this.editTokenWrapper = this.editToken.bind(this); this.tokenChange = this.tokenChange.bind(this); + this.addInputContainerFocusWrapper = this.addInputContainerFocus.bind(this); + this.removeInputContainerFocusWrapper = this.removeInputContainerFocus.bind(this); this.filteredSearchInputForm = this.filteredSearchInput.form; this.filteredSearchInputForm.addEventListener('submit', this.handleFormSubmit); @@ -51,11 +53,13 @@ import FilteredSearchContainer from './container'; this.filteredSearchInput.addEventListener('keyup', this.checkForBackspaceWrapper); this.filteredSearchInput.addEventListener('click', this.tokenChange); this.filteredSearchInput.addEventListener('keyup', this.tokenChange); + this.filteredSearchInput.addEventListener('focus', this.addInputContainerFocusWrapper); this.tokensContainer.addEventListener('click', FilteredSearchManager.selectToken); this.tokensContainer.addEventListener('dblclick', this.editTokenWrapper); this.clearSearchButton.addEventListener('click', this.clearSearchWrapper); document.addEventListener('click', gl.FilteredSearchVisualTokens.unselectTokens); document.addEventListener('click', this.unselectEditTokensWrapper); + document.addEventListener('click', this.removeInputContainerFocusWrapper); document.addEventListener('keydown', this.removeSelectedTokenWrapper); } @@ -69,11 +73,13 @@ import FilteredSearchContainer from './container'; this.filteredSearchInput.removeEventListener('keyup', this.checkForBackspaceWrapper); this.filteredSearchInput.removeEventListener('click', this.tokenChange); this.filteredSearchInput.removeEventListener('keyup', this.tokenChange); + this.filteredSearchInput.removeEventListener('focus', this.addInputContainerFocusWrapper); this.tokensContainer.removeEventListener('click', FilteredSearchManager.selectToken); this.tokensContainer.removeEventListener('dblclick', this.editTokenWrapper); this.clearSearchButton.removeEventListener('click', this.clearSearchWrapper); document.removeEventListener('click', gl.FilteredSearchVisualTokens.unselectTokens); document.removeEventListener('click', this.unselectEditTokensWrapper); + document.removeEventListener('click', this.removeInputContainerFocusWrapper); document.removeEventListener('keydown', this.removeSelectedTokenWrapper); } @@ -124,6 +130,26 @@ import FilteredSearchContainer from './container'; } } + addInputContainerFocus() { + const inputContainer = this.filteredSearchInput.closest('.filtered-search-input-container'); + + if (inputContainer) { + inputContainer.classList.add('focus'); + } + } + + removeInputContainerFocus(e) { + const inputContainer = this.filteredSearchInput.closest('.filtered-search-input-container'); + const isElementInFilteredSearch = inputContainer && inputContainer.contains(e.target); + const isElementInDynamicFilterDropdown = e.target.closest('.filter-dropdown') !== null; + const isElementInStaticFilterDropdown = e.target.closest('ul[data-dropdown]') !== null; + + if (!isElementInFilteredSearch && !isElementInDynamicFilterDropdown && + !isElementInStaticFilterDropdown && inputContainer) { + inputContainer.classList.remove('focus'); + } + } + static selectToken(e) { const button = e.target.closest('.selectable'); diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js index ef4029a8623..47e675f537e 100644 --- a/app/assets/javascripts/issue.js +++ b/app/assets/javascripts/issue.js @@ -2,6 +2,7 @@ /* global Flash */ require('./flash'); +require('~/lib/utils/text_utility'); require('vendor/jquery.waitforimages'); require('./task_list'); @@ -50,20 +51,21 @@ class Issue { success: function(data, textStatus, jqXHR) { if ('id' in data) { $(document).trigger('issuable:change'); - const currentTotal = Number($('.issue_counter').text()); + let total = Number($('.issue_counter').text().replace(/[^\d]/, '')); if (isClose) { $('a.btn-close').addClass('hidden'); $('a.btn-reopen').removeClass('hidden'); $('div.status-box-closed').removeClass('hidden'); $('div.status-box-open').addClass('hidden'); - $('.issue_counter').text(currentTotal - 1); + total -= 1; } else { $('a.btn-reopen').addClass('hidden'); $('a.btn-close').removeClass('hidden'); $('div.status-box-closed').addClass('hidden'); $('div.status-box-open').removeClass('hidden'); - $('.issue_counter').text(currentTotal + 1); + total += 1; } + $('.issue_counter').text(gl.text.addDelimiter(total)); } else { new Flash(issueFailMessage, 'alert'); } diff --git a/app/assets/javascripts/merge_request_widget.js b/app/assets/javascripts/merge_request_widget.js index 94a4f24f1d7..0e2af3df071 100644 --- a/app/assets/javascripts/merge_request_widget.js +++ b/app/assets/javascripts/merge_request_widget.js @@ -14,13 +14,13 @@ import MiniPipelineGraph from './mini_pipeline_graph_dropdown'; <%= ci_success_icon %> <span> Deployed to - <a href="<%- url %>" target="_blank" class="environment"> + <a href="<%- url %>" target="_blank" rel="noopener noreferrer" class="environment"> <%- name %> </a> <span class="js-environment-timeago" data-toggle="tooltip" data-placement="top" data-title="<%- deployed_at_formatted %>"> <%- deployed_at %> </span> - <a class="js-environment-link" href="<%- external_url %>" target="_blank"> + <a class="js-environment-link" href="<%- external_url %>" target="_blank" rel="noopener noreferrer"> <i class="fa fa-external-link"></i> View on <%- external_url_formatted %> </a> diff --git a/app/assets/javascripts/monitoring/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js new file mode 100644 index 00000000000..b3ce9310417 --- /dev/null +++ b/app/assets/javascripts/monitoring/monitoring_bundle.js @@ -0,0 +1,6 @@ +import PrometheusGraph from './prometheus_graph'; + +document.addEventListener('DOMContentLoaded', function onLoad() { + document.removeEventListener('DOMContentLoaded', onLoad, false); + return new PrometheusGraph(); +}, false); diff --git a/app/assets/javascripts/monitoring/prometheus_graph.js b/app/assets/javascripts/monitoring/prometheus_graph.js index 71eb746edac..fcffc11a2df 100644 --- a/app/assets/javascripts/monitoring/prometheus_graph.js +++ b/app/assets/javascripts/monitoring/prometheus_graph.js @@ -2,10 +2,9 @@ /* global Flash */ import d3 from 'd3'; -import _ from 'underscore'; import statusCodes from '~/lib/utils/http_status'; -import '~/lib/utils/common_utils'; -import '~/flash'; +import '../lib/utils/common_utils'; +import '../flash'; const prometheusGraphsContainer = '.prometheus-graph'; const metricsEndpoint = 'metrics.json'; @@ -31,22 +30,21 @@ class PrometheusGraph { } createGraph() { - const self = this; - _.each(this.data, (value, key) => { - if (value.length > 0 && (key === 'cpu_values' || key === 'memory_values')) { - self.plotValues(value, key); + Object.keys(this.data).forEach((key) => { + const value = this.data[key]; + if (value.length > 0) { + this.plotValues(value, key); } }); } init() { - const self = this; this.getData().then((metricsResponse) => { - if (metricsResponse === {}) { + if (Object.keys(metricsResponse).length === 0) { new Flash('Empty metrics', 'alert'); } else { - self.transformData(metricsResponse); - self.createGraph(); + this.transformData(metricsResponse); + this.createGraph(); } }); } @@ -321,12 +319,14 @@ class PrometheusGraph { transformData(metricsResponse) { const metricTypes = {}; - _.each(metricsResponse.metrics, (value, key) => { - const metricValues = value[0].values; - metricTypes[key] = _.map(metricValues, metric => ({ - time: new Date(metric[0] * 1000), - value: metric[1], - })); + Object.keys(metricsResponse.metrics).forEach((key) => { + if (key === 'cpu_values' || key === 'memory_values') { + const metricValues = (metricsResponse.metrics[key])[0]; + metricTypes[key] = metricValues.values.map(metric => ({ + time: new Date(metric[0] * 1000), + value: metric[1], + })); + } }); this.data = metricTypes; } diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index a4b38723bbd..2c33b235980 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -429,3 +429,9 @@ table { @include str-truncated(100%); } } + +.tooltip { + .tooltip-inner { + word-wrap: break-word; + } +} diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss index 2ebeaf9a40d..51805c5d734 100644 --- a/app/assets/stylesheets/framework/filters.scss +++ b/app/assets/stylesheets/framework/filters.scss @@ -76,12 +76,14 @@ } .input-token { - flex: 1; - -webkit-flex: 1; + max-width: 200px; } - .filtered-search-token + .input-token:not(:last-child) { - max-width: 200px; + .input-token:only-child, + .input-token:last-child { + flex: 1; + -webkit-flex: 1; + max-width: initial; } } @@ -158,8 +160,8 @@ background-color: $white-light; @media (max-width: $screen-xs-min) { - -webkit-flex: 1 1 100%; - flex: 1 1 100%; + -webkit-flex: 1 1 auto; + flex: 1 1 auto; margin-bottom: 10px; .dropdown-menu { @@ -171,17 +173,26 @@ } } + &:hover { + @extend .form-control:hover; + } + + &.focus, + &.focus:hover { + border-color: $dropdown-input-focus-border; + box-shadow: 0 0 4px $search-input-focus-shadow-color; + } + + &.focus .fa-filter { + color: $common-gray-dark; + } + .form-control { position: relative; min-width: 200px; - padding-left: 0; - padding-right: 25px; + padding: 5px 25px 6px 0; border-color: transparent; - &:focus ~ .fa-filter { - color: $common-gray-dark; - } - &:focus, &:hover { outline: none; @@ -221,6 +232,10 @@ .filter-dropdown-container { display: -webkit-flex; display: flex; + + .dropdown-toggle { + line-height: 22px; + } } .dropdown-menu .filter-dropdown-item { @@ -246,7 +261,9 @@ background-color: $white-light; border-top: 0; } +} +@media (max-width: $screen-xs) { .filter-dropdown-container { .dropdown-toggle, .dropdown { diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index c2156a5ac69..927bf9805ce 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -148,6 +148,18 @@ .error-alert > .alert { margin-top: 5px; margin-bottom: 5px; + + &.alert-dismissable { + .close { + color: $white-light; + opacity: 0.85; + font-weight: normal; + + &:hover { + opacity: 1; + } + } + } } .discussion-body, diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index f2fee62ebd6..cdb5b4173d3 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -6,6 +6,8 @@ class Projects::IssuesController < Projects::ApplicationController include IssuableCollections include SpammableActions + prepend_before_action :authenticate_user!, only: [:new] + before_action :redirect_to_external_issue_tracker, only: [:index, :new] before_action :module_enabled before_action :issue, only: [:edit, :update, :show, :referenced_merge_requests, @@ -146,7 +148,7 @@ class Projects::IssuesController < Projects::ApplicationController end format.json do - render json: @issue.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }, methods: [:task_status, :task_status_short]) + render json: @issue.to_json(include: { milestone: {}, assignee: { only: [:name, :username], methods: [:avatar_url] }, labels: { methods: :text_color } }, methods: [:task_status, :task_status_short]) end end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 82f9b6e06db..677a8a1a73a 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -308,7 +308,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController end format.json do - render json: @merge_request.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }, methods: [:task_status, :task_status_short]) + render json: @merge_request.to_json(include: { milestone: {}, assignee: { only: [:name, :username], methods: [:avatar_url] }, labels: { methods: :text_color } }, methods: [:task_status, :task_status_short]) end end rescue ActiveRecord::StaleObjectError diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 0b0c6a07efd..8631bc54509 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -215,6 +215,6 @@ module BlobHelper end def open_raw_file_button(path) - link_to icon('file-code-o'), path, class: 'btn btn-sm has-tooltip', target: '_blank', title: 'Open raw', data: { container: 'body' } + link_to icon('file-code-o'), path, class: 'btn btn-sm has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: 'Open raw', data: { container: 'body' } end end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 8aad39e148b..cef624430da 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -211,7 +211,7 @@ module CommitsHelper external_url = environment.external_url_for(diff_new_path, commit_sha) return unless external_url - link_to(external_url, class: 'btn btn-file-option has-tooltip', target: '_blank', title: "View on #{environment.formatted_external_url}", data: { container: 'body' }) do + link_to(external_url, class: 'btn btn-file-option has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: "View on #{environment.formatted_external_url}", data: { container: 'body' }) do icon('external-link') end end diff --git a/app/helpers/import_helper.rb b/app/helpers/import_helper.rb index a0642a1894b..a57b5a8fea5 100644 --- a/app/helpers/import_helper.rb +++ b/app/helpers/import_helper.rb @@ -7,7 +7,7 @@ module ImportHelper def provider_project_link(provider, path_with_namespace) url = __send__("#{provider}_project_url", path_with_namespace) - link_to path_with_namespace, url, target: '_blank' + link_to path_with_namespace, url, target: '_blank', rel: 'noopener noreferrer' end private diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index be632930895..671a0fe98cc 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -163,6 +163,8 @@ class ApplicationSetting < ActiveRecord::Base end def self.current + ensure_cache_setup + Rails.cache.fetch(CACHE_KEY) do ApplicationSetting.last end @@ -176,9 +178,16 @@ class ApplicationSetting < ActiveRecord::Base end def self.cached + ensure_cache_setup Rails.cache.fetch(CACHE_KEY) end + def self.ensure_cache_setup + # This is a workaround for a Rails bug that causes attribute methods not + # to be loaded when read from cache: https://github.com/rails/rails/issues/27348 + ApplicationSetting.define_attribute_methods + end + def self.defaults_ce { after_sign_up_text: nil, diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb index 5101cc7e687..0a1a65da05a 100644 --- a/app/models/concerns/has_status.rb +++ b/app/models/concerns/has_status.rb @@ -31,6 +31,7 @@ module HasStatus WHEN (#{builds})=(#{created})+(#{skipped})+(#{pending}) THEN 'pending' WHEN (#{running})+(#{pending})>0 THEN 'running' WHEN (#{manual})>0 THEN 'manual' + WHEN (#{created})>0 THEN 'running' ELSE 'failed' END)" end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 91f4eb13ecc..e7bd20b322a 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -48,11 +48,13 @@ module Issuable delegate :name, :email, + :public_email, to: :author, prefix: true delegate :name, :email, + :public_email, to: :assignee, allow_nil: true, prefix: true diff --git a/app/models/event.rb b/app/models/event.rb index d7ca8e3c599..5c34844b5d3 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -16,7 +16,7 @@ class Event < ActiveRecord::Base RESET_PROJECT_ACTIVITY_INTERVAL = 1.hour - delegate :name, :email, to: :author, prefix: true, allow_nil: true + delegate :name, :email, :public_email, to: :author, prefix: true, allow_nil: true delegate :title, to: :issue, prefix: true, allow_nil: true delegate :title, to: :merge_request, prefix: true, allow_nil: true delegate :title, to: :note, prefix: true, allow_nil: true diff --git a/app/models/project.rb b/app/models/project.rb index 17cf8226bcc..da4704554b3 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -196,6 +196,7 @@ class Project < ActiveRecord::Base validates :name, uniqueness: { scope: :namespace_id } validates :path, uniqueness: { scope: :namespace_id } validates :import_url, addressable_url: true, if: :external_import? + validates :import_url, importable_url: true, if: [:external_import?, :import_url_changed?] validates :star_count, numericality: { greater_than_or_equal_to: 0 } validate :check_limit, on: :create validate :avatar_type, @@ -880,13 +881,9 @@ class Project < ActiveRecord::Base end def http_url_to_repo(user = nil) - url = web_url + credentials = Gitlab::UrlSanitizer.http_credentials_for_user(user) - if user - url.sub!(%r{\Ahttps?://}) { |protocol| "#{protocol}#{user.username}@" } - end - - "#{url}.git" + Gitlab::UrlSanitizer.new("#{web_url}.git", credentials: credentials).full_url end # Check if current branch name is marked as protected in the system diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index 539b31780b3..70eef359cdd 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -42,8 +42,11 @@ class ProjectWiki url_to_repo end - def http_url_to_repo - [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('') + def http_url_to_repo(user = nil) + url = "#{Gitlab.config.gitlab.url}/#{path_with_namespace}.git" + credentials = Gitlab::UrlSanitizer.http_credentials_for_user(user) + + Gitlab::UrlSanitizer.new(url, credentials: credentials).full_url end def wiki_base_path diff --git a/app/models/route.rb b/app/models/route.rb index 73574a6206b..41e6eb7cb73 100644 --- a/app/models/route.rb +++ b/app/models/route.rb @@ -21,7 +21,7 @@ class Route < ActiveRecord::Base attributes[:path] = route.path.sub(path_was, path) end - if name_changed? && route.name.present? + if name_changed? && name_was.present? && route.name.present? attributes[:name] = route.name.sub(name_was, name) end diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb index 1c5a549feb9..d484a96f785 100644 --- a/app/services/projects/import_service.rb +++ b/app/services/projects/import_service.rb @@ -33,6 +33,7 @@ module Projects def import_repository begin + raise Error, "Blocked import URL." if Gitlab::UrlBlocker.blocked_url?(project.import_url) gitlab_shell.import_repository(project.repository_storage_path, project.path_with_namespace, project.import_url) rescue => e # Expire cache to prevent scenarios such as: @@ -40,7 +41,7 @@ module Projects # 2. Retried import, repo is broken or not imported but +exists?+ still returns true project.repository.before_import if project.repository_exists? - raise Error, "Error importing repository #{project.import_url} into #{project.path_with_namespace} - #{e.message}" + raise Error, "Error importing repository #{project.import_url} into #{project.path_with_namespace} - #{e.message}" end end diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb index 868fa7b3f21..af0ddbe5934 100644 --- a/app/services/system_hooks_service.rb +++ b/app/services/system_hooks_service.rb @@ -24,10 +24,9 @@ class SystemHooksService key: model.key, id: model.id ) + if model.user - data.merge!( - username: model.user.username - ) + data[:username] = model.user.username end when Project data.merge!(project_data(model)) @@ -35,8 +34,6 @@ class SystemHooksService if event == :rename || event == :transfer data[:old_path_with_namespace] = model.old_path_with_namespace end - - data when User data.merge!({ name: model.name, @@ -59,6 +56,8 @@ class SystemHooksService when GroupMember data.merge!(group_member_data(model)) end + + data end def build_event_name(model, event) diff --git a/app/validators/importable_url_validator.rb b/app/validators/importable_url_validator.rb new file mode 100644 index 00000000000..37a314adee6 --- /dev/null +++ b/app/validators/importable_url_validator.rb @@ -0,0 +1,11 @@ +# ImportableUrlValidator +# +# This validator blocks projects from using dangerous import_urls to help +# protect against Server-side Request Forgery (SSRF). +class ImportableUrlValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + if Gitlab::UrlBlocker.blocked_url?(value) + record.errors.add(attribute, "imports are not allowed from that URL") + end + end +end diff --git a/app/views/admin/appearances/_form.html.haml b/app/views/admin/appearances/_form.html.haml index 9175b3d3f96..e403a9da616 100644 --- a/app/views/admin/appearances/_form.html.haml +++ b/app/views/admin/appearances/_form.html.haml @@ -48,7 +48,7 @@ .form-actions = f.submit 'Save', class: 'btn btn-save append-right-10' - if @appearance.persisted? - = link_to 'Preview last save', preview_admin_appearances_path, class: 'btn', target: '_blank' + = link_to 'Preview last save', preview_admin_appearances_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer' - if @appearance.updated_at %span.pull-right diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 00366b0a8c9..3eab065bb9f 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -404,7 +404,7 @@ Enable Sentry .help-block Sentry is an error reporting and logging tool which is currently not shipped with GitLab, get it here: - %a{ href: 'https://getsentry.com', target: '_blank' } https://getsentry.com + %a{ href: 'https://getsentry.com', target: '_blank', rel: 'noopener noreferrer' } https://getsentry.com .form-group = f.label :sentry_dsn, 'Sentry DSN', class: 'control-label col-sm-2' diff --git a/app/views/events/_event.atom.builder b/app/views/events/_event.atom.builder index 43a52cf3002..158061579f6 100644 --- a/app/views/events/_event.atom.builder +++ b/app/views/events/_event.atom.builder @@ -9,7 +9,7 @@ xml.entry do xml.author do xml.name event.author_name - xml.email event.author_email + xml.email event.author_public_email end xml.summary(type: "xhtml") do |summary| diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml index f08c96df309..64b5a733b77 100644 --- a/app/views/events/event/_note.html.haml +++ b/app/views/events/event/_note.html.haml @@ -15,6 +15,6 @@ = link_to note.attachment.url, target: '_blank' do = image_tag note.attachment.url, class: 'note-image-attach' - else - = link_to note.attachment.url, target: "_blank", class: 'note-file-attach' do + = link_to note.attachment.url, target: '_blank', class: 'note-file-attach' do %i.fa.fa-paperclip = note.attachment_identifier diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index 31631887317..f93b6b63426 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -17,7 +17,7 @@ %br Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises. %br - Read more about GitLab at #{link_to promo_host, promo_url, target: '_blank'}. + Read more about GitLab at #{link_to promo_host, promo_url, target: '_blank', rel: 'noopener noreferrer'}. - if current_application_settings.help_page_text.present? %hr = markdown_field(current_application_settings, :help_page_text) diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml index e18bd47798b..e6058617ac9 100644 --- a/app/views/import/bitbucket/status.html.haml +++ b/app/views/import/bitbucket/status.html.haml @@ -33,7 +33,7 @@ - @already_added_projects.each do |project| %tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" } %td - = link_to project.import_source, "https://bitbucket.org/#{project.import_source}", target: '_blank' + = link_to project.import_source, "https://bitbucket.org/#{project.import_source}", target: '_blank', rel: 'noopener noreferrer' %td = link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project] %td.job-status @@ -50,7 +50,7 @@ - @repos.each do |repo| %tr{ id: "repo_#{repo.owner}___#{repo.slug}" } %td - = link_to repo.full_name, "https://bitbucket.org/#{repo.full_name}", target: "_blank" + = link_to repo.full_name, "https://bitbucket.org/#{repo.full_name}", target: '_blank', rel: 'noopener noreferrer' %td.import-target %fieldset.row .input-group @@ -70,7 +70,7 @@ - @incompatible_repos.each do |repo| %tr{ id: "repo_#{repo.owner}___#{repo.slug}" } %td - = link_to repo.full_name, "https://bitbucket.org/#{repo.full_name}", target: '_blank' + = link_to repo.full_name, "https://bitbucket.org/#{repo.full_name}", target: '_blank', rel: 'noopener noreferrer' %td.import-target %td.import-actions-job-status = label_tag 'Incompatible Project', nil, class: 'label label-danger' diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml index d5b88709a34..7456799ca0e 100644 --- a/app/views/import/gitlab/status.html.haml +++ b/app/views/import/gitlab/status.html.haml @@ -43,7 +43,7 @@ - @repos.each do |repo| %tr{ id: "repo_#{repo["id"]}" } %td - = link_to repo["path_with_namespace"], "https://gitlab.com/#{repo["path_with_namespace"]}", target: "_blank" + = link_to repo["path_with_namespace"], "https://gitlab.com/#{repo["path_with_namespace"]}", target: "_blank", rel: 'noopener noreferrer' %td.import-target = import_project_target(repo['namespace']['path'], repo['name']) %td.import-actions.job-status diff --git a/app/views/import/google_code/new.html.haml b/app/views/import/google_code/new.html.haml index 336becd229e..c5800a1cca0 100644 --- a/app/views/import/google_code/new.html.haml +++ b/app/views/import/google_code/new.html.haml @@ -13,7 +13,7 @@ %li %p Go to - #{link_to "Google Takeout", "https://www.google.com/settings/takeout", target: "_blank"}. + #{link_to "Google Takeout", "https://www.google.com/settings/takeout", target: '_blank', rel: 'noopener noreferrer'}. %li %p Make sure you're logged into the account that owns the projects you'd like to import. diff --git a/app/views/import/google_code/status.html.haml b/app/views/import/google_code/status.html.haml index 5e01af008be..60de6bfe816 100644 --- a/app/views/import/google_code/status.html.haml +++ b/app/views/import/google_code/status.html.haml @@ -36,7 +36,7 @@ - @already_added_projects.each do |project| %tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" } %td - = link_to project.import_source, "https://code.google.com/p/#{project.import_source}", target: "_blank" + = link_to project.import_source, "https://code.google.com/p/#{project.import_source}", target: "_blank", rel: 'noopener noreferrer' %td = link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project] %td.job-status @@ -53,7 +53,7 @@ - @repos.each do |repo| %tr{ id: "repo_#{repo.id}" } %td - = link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank" + = link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank", rel: 'noopener noreferrer' %td.import-target #{current_user.username}/#{repo.name} %td.import-actions.job-status @@ -63,7 +63,7 @@ - @incompatible_repos.each do |repo| %tr{ id: "repo_#{repo.id}" } %td - = link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank" + = link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank", rel: 'noopener noreferrer' %td.import-target %td.import-actions-job-status = label_tag "Incompatible Project", nil, class: "label label-danger" diff --git a/app/views/issues/_issue.atom.builder b/app/views/issues/_issue.atom.builder index fcd30c8c765..23a88448055 100644 --- a/app/views/issues/_issue.atom.builder +++ b/app/views/issues/_issue.atom.builder @@ -7,7 +7,7 @@ xml.entry do xml.author do xml.name issue.author_name - xml.email issue.author_email + xml.email issue.author_public_email end xml.summary issue.title @@ -26,7 +26,7 @@ xml.entry do if issue.assignee xml.assignee do xml.name issue.assignee.name - xml.email issue.assignee.email + xml.email issue.assignee_public_email end end end diff --git a/app/views/koding/index.html.haml b/app/views/koding/index.html.haml index 65887aacbaf..04e2d4b63e6 100644 --- a/app/views/koding/index.html.haml +++ b/app/views/koding/index.html.haml @@ -2,5 +2,5 @@ %p = icon('circle', class: 'cgreen') Integration is active for - = link_to koding_project_url, target: '_blank' do + = link_to koding_project_url, target: '_blank', rel: 'noopener noreferrer' do #{current_application_settings.koding_url} diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index d551754a2e5..c74b3249a13 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -18,7 +18,7 @@ or change it at #{link_to Gitlab.config.gravatar.host, "http://" + Gitlab.config.gravatar.host} .col-lg-9 .clearfix.avatar-image.append-bottom-default - = link_to avatar_icon(@user, 400), target: '_blank' do + = link_to avatar_icon(@user, 400), target: '_blank', rel: 'noopener noreferrer' do = image_tag avatar_icon(@user, 160), alt: '', class: 'avatar s160' %h5.prepend-top-0 Upload new avatar diff --git a/app/views/projects/blob/_image.html.haml b/app/views/projects/blob/_image.html.haml index f864702d862..ea3cecb86a9 100644 --- a/app/views/projects/blob/_image.html.haml +++ b/app/views/projects/blob/_image.html.haml @@ -9,7 +9,7 @@ - else .nothing-here-block The SVG could not be displayed as it is too large, you can - #{link_to('view the raw file', namespace_project_raw_path(@project.namespace, @project, @id), target: '_blank')} + #{link_to('view the raw file', namespace_project_raw_path(@project.namespace, @project, @id), target: '_blank', rel: 'noopener noreferrer')} instead. - else %img{ src: namespace_project_raw_path(@project.namespace, @project, tree_join(@commit.id, blob.path)), alt: "#{blob.name}" } diff --git a/app/views/projects/blob/_text.html.haml b/app/views/projects/blob/_text.html.haml index b1e1be49de9..7b16d266982 100644 --- a/app/views/projects/blob/_text.html.haml +++ b/app/views/projects/blob/_text.html.haml @@ -3,7 +3,7 @@ .nothing-here-block File too large, you can = succeed '.' do - = link_to 'view the raw file', namespace_project_raw_path(@project.namespace, @project, @id), target: '_blank' + = link_to 'view the raw file', namespace_project_raw_path(@project.namespace, @project, @id), target: '_blank', rel: 'noopener noreferrer' - else - blob.load_all_data!(@repository) diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml index 8853801016b..3bcddcb37f1 100644 --- a/app/views/projects/blob/edit.html.haml +++ b/app/views/projects/blob/edit.html.haml @@ -9,7 +9,7 @@ - if @conflict .alert.alert-danger Someone edited the file the same time you did. Please check out - = link_to "the file", namespace_project_blob_path(@project.namespace, @project, tree_join(@target_branch, @file_path)), target: "_blank" + = link_to "the file", namespace_project_blob_path(@project.namespace, @project, tree_join(@target_branch, @file_path)), target: "_blank", rel: 'noopener noreferrer' and make sure your changes will not unintentionally remove theirs. .file-editor diff --git a/app/views/projects/buttons/_koding.html.haml b/app/views/projects/buttons/_koding.html.haml index 5d9a776da89..a5a9e4d0621 100644 --- a/app/views/projects/buttons/_koding.html.haml +++ b/app/views/projects/buttons/_koding.html.haml @@ -1,3 +1,3 @@ - if koding_enabled? && current_user && @repository.koding_yml && can_push_branch?(@project, @project.default_branch) - = link_to koding_project_url(@project), class: 'btn project-action-button inline', target: '_blank' do + = link_to koding_project_url(@project), class: 'btn project-action-button inline', target: '_blank', rel: 'noopener noreferrer' do Run in IDE (Koding) diff --git a/app/views/projects/cycle_analytics/_overview.html.haml b/app/views/projects/cycle_analytics/_overview.html.haml index c8f0b547f80..9007f2c24ba 100644 --- a/app/views/projects/cycle_analytics/_overview.html.haml +++ b/app/views/projects/cycle_analytics/_overview.html.haml @@ -9,7 +9,7 @@ Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project. To set up CA, you must first define a production environment by setting up your CI and then deploy to production. %p - %a.btn{ href: help_page_path('user/project/cycle_analytics'), target: "_blank" } Read more + %a.btn{ href: help_page_path('user/project/cycle_analytics'), target: '_blank' } Read more .col-md-6.overview-image %span.overview-icon = custom_icon ('icon_cycle_analytics_overview') diff --git a/app/views/projects/environments/_external_url.html.haml b/app/views/projects/environments/_external_url.html.haml index 4c8fe1c271b..bf0f1819073 100644 --- a/app/views/projects/environments/_external_url.html.haml +++ b/app/views/projects/environments/_external_url.html.haml @@ -1,3 +1,3 @@ - if environment.external_url && can?(current_user, :read_environment, environment) - = link_to environment.external_url, target: '_blank', class: 'btn external-url' do + = link_to environment.external_url, target: '_blank', rel: 'noopener noreferrer', class: 'btn external-url' do = icon('external-link') diff --git a/app/views/projects/environments/metrics.html.haml b/app/views/projects/environments/metrics.html.haml index f8e94ca98ae..b8c1782f050 100644 --- a/app/views/projects/environments/metrics.html.haml +++ b/app/views/projects/environments/metrics.html.haml @@ -1,5 +1,8 @@ - @no_container = true - page_title "Metrics for environment", @environment.name +- content_for :page_specific_javascripts do + = page_specific_javascript_bundle_tag('common_d3') + = page_specific_javascript_bundle_tag('monitoring') = render "projects/pipelines/head" %div{ class: container_class } diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index 7b7d7b1e00e..f3a429d12d9 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -19,15 +19,14 @@ .nav-controls = link_to params.merge(rss_url_options), class: 'btn append-right-10 has-tooltip', title: 'Subscribe' do = icon('rss') - - if can? current_user, :create_issue, @project - = link_to new_namespace_project_issue_path(@project.namespace, - @project, - issue: { assignee_id: issues_finder.assignee.try(:id), - milestone_id: issues_finder.milestones.first.try(:id) }), - class: "btn btn-new", - title: "New Issue", - id: "new_issue_link" do - New Issue + = link_to new_namespace_project_issue_path(@project.namespace, + @project, + issue: { assignee_id: issues_finder.assignee.try(:id), + milestone_id: issues_finder.milestones.first.try(:id) }), + class: "btn btn-new", + title: "New Issue", + id: "new_issue_link" do + New Issue = render 'shared/issuable/search_bar', type: :issues .issues-holder diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index d39f36e94c7..6ac05bf3afe 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -20,37 +20,34 @@ = confidential_icon(@issue) = issuable_meta(@issue, @project, "Issue") - - if can?(current_user, :create_issue, @project) || can?(current_user, :update_issue, @issue) - .issuable-actions - .clearfix.issue-btn-group.dropdown - %button.btn.btn-default.pull-left.hidden-md.hidden-lg{ type: "button", data: { toggle: "dropdown" } } - Options - = icon('caret-down') - .dropdown-menu.dropdown-menu-align-right.hidden-lg - %ul - - if can?(current_user, :create_issue, @project) - %li - = link_to 'New issue', new_namespace_project_issue_path(@project.namespace, @project), title: 'New issue', id: 'new_issue_link' - - if can?(current_user, :update_issue, @issue) - %li - = link_to 'Reopen issue', issue_path(@issue, issue: { state_event: :reopen }, format: 'json'), data: {no_turbolink: true}, class: "btn-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue' - %li - = link_to 'Close issue', issue_path(@issue, issue: { state_event: :close }, format: 'json'), data: {no_turbolink: true}, class: "btn-close #{issue_button_visibility(@issue, true)}", title: 'Close issue' - %li - = link_to 'Edit', edit_namespace_project_issue_path(@project.namespace, @project, @issue) - - if @issue.submittable_as_spam_by?(current_user) - %li - = link_to 'Submit as spam', mark_as_spam_namespace_project_issue_path(@project.namespace, @project, @issue), method: :post, class: 'btn-spam', title: 'Submit as spam' - - - if can?(current_user, :create_issue, @project) - = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'hidden-xs hidden-sm btn btn-grouped new-issue-link btn-new btn-inverted', title: 'New issue', id: 'new_issue_link' do - New issue - - if can?(current_user, :update_issue, @issue) - = link_to 'Reopen issue', issue_path(@issue, issue: { state_event: :reopen }, format: 'json'), data: {no_turbolink: true}, class: "hidden-xs hidden-sm btn btn-grouped btn-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue' - = link_to 'Close issue', issue_path(@issue, issue: { state_event: :close }, format: 'json'), data: {no_turbolink: true}, class: "hidden-xs hidden-sm btn btn-grouped btn-close #{issue_button_visibility(@issue, true)}", title: 'Close issue' + .issuable-actions + .clearfix.issue-btn-group.dropdown + %button.btn.btn-default.pull-left.hidden-md.hidden-lg{ type: "button", data: { toggle: "dropdown" } } + Options + = icon('caret-down') + .dropdown-menu.dropdown-menu-align-right.hidden-lg + %ul + %li + = link_to 'New issue', new_namespace_project_issue_path(@project.namespace, @project), title: 'New issue', id: 'new_issue_link' + - if can?(current_user, :update_issue, @issue) + %li + = link_to 'Reopen issue', issue_path(@issue, issue: { state_event: :reopen }, format: 'json'), data: {no_turbolink: true}, class: "btn-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue' + %li + = link_to 'Close issue', issue_path(@issue, issue: { state_event: :close }, format: 'json'), data: {no_turbolink: true}, class: "btn-close #{issue_button_visibility(@issue, true)}", title: 'Close issue' + %li + = link_to 'Edit', edit_namespace_project_issue_path(@project.namespace, @project, @issue) - if @issue.submittable_as_spam_by?(current_user) - = link_to 'Submit as spam', mark_as_spam_namespace_project_issue_path(@project.namespace, @project, @issue), method: :post, class: 'hidden-xs hidden-sm btn btn-grouped btn-spam', title: 'Submit as spam' - = link_to 'Edit', edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: 'hidden-xs hidden-sm btn btn-grouped issuable-edit' + %li + = link_to 'Submit as spam', mark_as_spam_namespace_project_issue_path(@project.namespace, @project, @issue), method: :post, class: 'btn-spam', title: 'Submit as spam' + + = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'hidden-xs hidden-sm btn btn-grouped new-issue-link btn-new btn-inverted', title: 'New issue', id: 'new_issue_link' do + New issue + - if can?(current_user, :update_issue, @issue) + = link_to 'Reopen issue', issue_path(@issue, issue: { state_event: :reopen }, format: 'json'), data: {no_turbolink: true}, class: "hidden-xs hidden-sm btn btn-grouped btn-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue' + = link_to 'Close issue', issue_path(@issue, issue: { state_event: :close }, format: 'json'), data: {no_turbolink: true}, class: "hidden-xs hidden-sm btn btn-grouped btn-close #{issue_button_visibility(@issue, true)}", title: 'Close issue' + - if @issue.submittable_as_spam_by?(current_user) + = link_to 'Submit as spam', mark_as_spam_namespace_project_issue_path(@project.namespace, @project, @issue), method: :post, class: 'hidden-xs hidden-sm btn btn-grouped btn-spam', title: 'Submit as spam' + = link_to 'Edit', edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: 'hidden-xs hidden-sm btn btn-grouped issuable-edit' .issue-details.issuable-details diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index c8f097c69da..6682a85ffa6 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -16,7 +16,7 @@ .pull-right - if @merge_request.source_branch_exists? - if koding_enabled? && @repository.koding_yml - = link_to koding_project_url(@merge_request.source_project, @merge_request.source_branch, @merge_request.commits.first.short_id), class: "btn inline btn-grouped btn-sm", target: '_blank' do + = link_to koding_project_url(@merge_request.source_project, @merge_request.source_branch, @merge_request.commits.first.short_id), class: "btn inline btn-grouped btn-sm", target: '_blank', rel: 'noopener noreferrer' do Run in IDE (Koding) = link_to "#modal_merge_info", class: "btn inline btn-grouped btn-sm", "data-toggle" => "modal" do Check out branch diff --git a/app/views/projects/merge_requests/show/_how_to_merge.html.haml b/app/views/projects/merge_requests/show/_how_to_merge.html.haml index 93ed4b68e0e..cde0ce08e14 100644 --- a/app/views/projects/merge_requests/show/_how_to_merge.html.haml +++ b/app/views/projects/merge_requests/show/_how_to_merge.html.haml @@ -49,7 +49,7 @@ %strong Tip: = succeed '.' do You can also checkout merge requests locally by - = link_to 'following these guidelines', help_page_path('user/project/merge_requests.md', anchor: "checkout-merge-requests-locally"), target: '_blank' + = link_to 'following these guidelines', help_page_path('user/project/merge_requests.md', anchor: "checkout-merge-requests-locally"), target: '_blank', rel: 'noopener noreferrer' :javascript $(function(){ diff --git a/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml index 3a323d94cc2..2fb88297fb3 100644 --- a/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml +++ b/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml @@ -4,13 +4,13 @@ %ul.list-unstyled.indent-list %li 1. - = link_to 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands', target: '_blank', rel: 'noreferrer noopener nofollow' do + = link_to 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands', target: '_blank', rel: 'noopener noreferrer nofollow' do Enable custom slash commands = icon('external-link') on your Mattermost installation %li 2. - = link_to 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command', target: '_blank', rel: 'noreferrer noopener nofollow' do + = link_to 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command', target: '_blank', rel: 'noopener noreferrer nofollow' do Add a slash command = icon('external-link') in your Mattermost team with these options: diff --git a/app/views/projects/services/mattermost_slash_commands/_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_help.html.haml index a04fd5035a6..2a1b9d4c465 100644 --- a/app/views/projects/services/mattermost_slash_commands/_help.html.haml +++ b/app/views/projects/services/mattermost_slash_commands/_help.html.haml @@ -4,7 +4,7 @@ %p This service allows users to perform common operations on this project by entering slash commands in Mattermost. - = link_to help_page_path('user/project/integrations/mattermost_slash_commands.md'), target: '_blank', ref: 'noreferrer nofollow noopener' do + = link_to help_page_path('user/project/integrations/mattermost_slash_commands.md'), target: '_blank' do View documentation = icon('external-link') %p.inline diff --git a/app/views/projects/services/slack_slash_commands/_help.html.haml b/app/views/projects/services/slack_slash_commands/_help.html.haml index 0d973a20d4c..078b7be6865 100644 --- a/app/views/projects/services/slack_slash_commands/_help.html.haml +++ b/app/views/projects/services/slack_slash_commands/_help.html.haml @@ -5,7 +5,7 @@ %p This service allows users to perform common operations on this project by entering slash commands in Slack. - = link_to help_page_path('user/project/integrations/slack_slash_commands.md'), target: '_blank', ref: 'noreferrer nofollow noopener' do + = link_to help_page_path('user/project/integrations/slack_slash_commands.md'), target: '_blank' do View documentation = icon('external-link') %p.inline @@ -57,7 +57,7 @@ = label_tag nil, 'Customize icon', class: 'col-sm-2 col-xs-12 control-label' .col-sm-10.col-xs-12.text-block = image_tag(asset_url('slash-command-logo.png'), width: 36, height: 36) - = link_to('Download image', asset_url('gitlab_logo.png'), class: 'btn btn-sm', target: '_blank') + = link_to('Download image', asset_url('gitlab_logo.png'), class: 'btn btn-sm', target: '_blank', rel: 'noopener noreferrer') .form-group = label_tag nil, 'Autocomplete', class: 'col-sm-2 col-xs-12 control-label' diff --git a/app/views/shared/_sort_dropdown.html.haml b/app/views/shared/_sort_dropdown.html.haml index 367aa550a78..a212c714826 100644 --- a/app/views/shared/_sort_dropdown.html.haml +++ b/app/views/shared/_sort_dropdown.html.haml @@ -1,6 +1,5 @@ .dropdown.inline.prepend-left-10 %button.dropdown-toggle{ type: 'button', data: {toggle: 'dropdown' } } - %span.light - if @sort.present? = sort_options_hash[@sort] - else diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml index e2033654018..7a7e3d46796 100644 --- a/app/views/shared/empty_states/_issues.html.haml +++ b/app/views/shared/empty_states/_issues.html.haml @@ -16,7 +16,6 @@ Also, issues are searchable and filterable. - if project_select_button = render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue' - - else - = link_to 'New issue', button_path, class: 'btn btn-new', title: 'New issue', id: 'new_issue_link' - else - %h4.text-center There are no issues to show. + %h4 There are no issues to show. + = link_to 'New issue', button_path, class: 'btn btn-new', title: 'New issue', id: 'new_issue_link' diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 0b0f2c9cd1a..17107f55a2d 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -8,7 +8,7 @@ .alert.alert-danger Someone edited the #{issuable.class.model_name.human.downcase} the same time you did. Please check out - = link_to "the #{issuable.class.model_name.human.downcase}", polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), target: "_blank" + = link_to "the #{issuable.class.model_name.human.downcase}", polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), target: "_blank", rel: 'noopener noreferrer' and make sure your changes will not unintentionally remove theirs .form-group diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 76cd330e80a..dc9a3b0d0df 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -33,7 +33,7 @@ .profile-header .avatar-holder - = link_to avatar_icon(@user, 400), target: '_blank' do + = link_to avatar_icon(@user, 400), target: '_blank', rel: 'noopener noreferrer' do = image_tag avatar_icon(@user, 90), class: "avatar s90", alt: '' .user-info |