diff options
author | Marin Jankovski <maxlazio@gmail.com> | 2017-09-01 10:21:18 +0300 |
---|---|---|
committer | Marin Jankovski <maxlazio@gmail.com> | 2017-09-01 10:21:18 +0300 |
commit | 28060caa0ade7566a38e3ed17f2db8bf9116dc1b (patch) | |
tree | 3886373472541059bf04cd95dbc4595189f0d600 /app | |
parent | 7d38df306c73af354286cecb24b19155e537797b (diff) | |
parent | 6f96ccaa7dd53a7462b86a0ebe8af66afde86aa2 (diff) |
Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce
Diffstat (limited to 'app')
43 files changed, 349 insertions, 95 deletions
diff --git a/app/assets/javascripts/commons/polyfills.js b/app/assets/javascripts/commons/polyfills.js index bc3e741f524..b78089525cc 100644 --- a/app/assets/javascripts/commons/polyfills.js +++ b/app/assets/javascripts/commons/polyfills.js @@ -12,3 +12,4 @@ import 'core-js/fn/symbol'; // Browser polyfills import './polyfills/custom_event'; import './polyfills/element'; +import './polyfills/nodelist'; diff --git a/app/assets/javascripts/commons/polyfills/nodelist.js b/app/assets/javascripts/commons/polyfills/nodelist.js new file mode 100644 index 00000000000..3772c94b900 --- /dev/null +++ b/app/assets/javascripts/commons/polyfills/nodelist.js @@ -0,0 +1,7 @@ +if (window.NodeList && !NodeList.prototype.forEach) { + NodeList.prototype.forEach = function forEach(callback, thisArg = window) { + for (let i = 0; i < this.length; i += 1) { + callback.call(thisArg, this[i], i, this); + } + }; +} diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index b71c449090e..c70a17104fd 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -74,6 +74,7 @@ import PerformanceBar from './performance_bar'; import initNotes from './init_notes'; import initLegacyFilters from './init_legacy_filters'; import initIssuableSidebar from './init_issuable_sidebar'; +import initProjectVisibilitySelector from './project_visibility'; import GpgBadges from './gpg_badges'; import UserFeatureHelper from './helpers/user_feature_helper'; import initChangesDropdown from './init_changes_dropdown'; @@ -575,6 +576,7 @@ import initChangesDropdown from './init_changes_dropdown'; break; case 'new': new ProjectNew(); + initProjectVisibilitySelector(); break; case 'show': new Star(); diff --git a/app/assets/javascripts/lib/utils/pretty_time.js b/app/assets/javascripts/lib/utils/pretty_time.js index 716aefbfcb7..227bf65b560 100644 --- a/app/assets/javascripts/lib/utils/pretty_time.js +++ b/app/assets/javascripts/lib/utils/pretty_time.js @@ -2,19 +2,20 @@ import _ from 'underscore'; (() => { /* - * TODO: Make these methods more configurable (e.g. parseSeconds timePeriodContstraints, - * stringifyTime condensed or non-condensed, abbreviateTimelengths) + * TODO: Make these methods more configurable (e.g. stringifyTime condensed or + * non-condensed, abbreviateTimelengths) * */ const utils = window.gl.utils = gl.utils || {}; const prettyTime = utils.prettyTime = { /* * Accepts seconds and returns a timeObject { weeks: #, days: #, hours: #, minutes: # } - * Seconds can be negative or positive, zero or non-zero. + * Seconds can be negative or positive, zero or non-zero. Can be configured for any day + * or week length. */ - parseSeconds(seconds) { - const DAYS_PER_WEEK = 5; - const HOURS_PER_DAY = 8; + parseSeconds(seconds, { daysPerWeek = 5, hoursPerDay = 8 } = {}) { + const DAYS_PER_WEEK = daysPerWeek; + const HOURS_PER_DAY = hoursPerDay; const MINUTES_PER_HOUR = 60; const MINUTES_PER_WEEK = DAYS_PER_WEEK * HOURS_PER_DAY * MINUTES_PER_HOUR; const MINUTES_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR; diff --git a/app/assets/javascripts/project_select_combo_button.js b/app/assets/javascripts/project_select_combo_button.js index 46a26fb91f4..99cea683d9a 100644 --- a/app/assets/javascripts/project_select_combo_button.js +++ b/app/assets/javascripts/project_select_combo_button.js @@ -14,7 +14,14 @@ export default class ProjectSelectComboButton { bindEvents() { this.projectSelectInput.siblings('.new-project-item-select-button') - .on('click', this.openDropdown); + .on('click', e => this.openDropdown(e)); + + this.newItemBtn.on('click', (e) => { + if (!this.getProjectFromLocalStorage()) { + e.preventDefault(); + this.openDropdown(e); + } + }); this.projectSelectInput.on('change', () => this.selectProject()); } @@ -28,8 +35,9 @@ export default class ProjectSelectComboButton { } } - openDropdown() { - $(this).siblings('.project-item-select').select2('open'); + // eslint-disable-next-line class-methods-use-this + openDropdown(event) { + $(event.currentTarget).siblings('.project-item-select').select2('open'); } selectProject() { @@ -56,10 +64,8 @@ export default class ProjectSelectComboButton { if (project) { this.newItemBtn.attr('href', project.url); this.newItemBtn.text(`${this.formattedText.defaultTextPrefix} in ${project.name}`); - this.newItemBtn.enable(); } else { this.newItemBtn.text(`Select project to create ${this.formattedText.presetTextSuffix}`); - this.newItemBtn.disable(); } } diff --git a/app/assets/javascripts/project_visibility.js b/app/assets/javascripts/project_visibility.js new file mode 100644 index 00000000000..c3f5e8cb907 --- /dev/null +++ b/app/assets/javascripts/project_visibility.js @@ -0,0 +1,41 @@ +function setVisibilityOptions(namespaceSelector) { + if (!namespaceSelector || !('selectedIndex' in namespaceSelector)) { + return; + } + const selectedNamespace = namespaceSelector.options[namespaceSelector.selectedIndex]; + const { name, visibility, visibilityLevel, showPath, editPath } = selectedNamespace.dataset; + + document.querySelectorAll('.visibility-level-setting .radio').forEach((option) => { + const optionInput = option.querySelector('input[type=radio]'); + const optionValue = optionInput ? optionInput.value : 0; + const optionTitle = option.querySelector('.option-title'); + const optionName = optionTitle ? optionTitle.innerText.toLowerCase() : ''; + + // don't change anything if the option is restricted by admin + if (!option.classList.contains('restricted')) { + if (visibilityLevel < optionValue) { + option.classList.add('disabled'); + optionInput.disabled = true; + const reason = option.querySelector('.option-disabled-reason'); + if (reason) { + reason.innerHTML = + `This project cannot be ${optionName} because the visibility of + <a href="${showPath}">${name}</a> is ${visibility}. To make this project + ${optionName}, you must first <a href="${editPath}">change the visibility</a> + of the parent group.`; + } + } else { + option.classList.remove('disabled'); + optionInput.disabled = false; + } + } + }); +} + +export default function initProjectVisibilitySelector() { + const namespaceSelector = document.querySelector('select.js-select-namespace'); + if (namespaceSelector) { + $('.select2.js-select-namespace').on('change', () => setVisibilityOptions(namespaceSelector)); + setVisibilityOptions(namespaceSelector); + } +} diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue index 262584769e0..50d14282cad 100644 --- a/app/assets/javascripts/vue_shared/components/commit.vue +++ b/app/assets/javascripts/vue_shared/components/commit.vue @@ -1,6 +1,7 @@ <script> import commitIconSvg from 'icons/_icon_commit.svg'; import userAvatarLink from './user_avatar/user_avatar_link.vue'; + import tooltip from '../directives/tooltip'; export default { props: { @@ -100,17 +101,22 @@ this.author.username ? `${this.author.username}'s avatar` : null; }, }, - data() { - return { commitIconSvg }; + directives: { + tooltip, }, components: { userAvatarLink, }, + created() { + this.commitIconSvg = commitIconSvg; + }, }; </script> <template> <div class="branch-commit"> - <div v-if="hasCommitRef" class="icon-container hidden-xs"> + <div + v-if="hasCommitRef" + class="icon-container hidden-xs"> <i v-if="tag" class="fa fa-tag" @@ -126,7 +132,10 @@ <a v-if="hasCommitRef" class="ref-name hidden-xs" - :href="commitRef.ref_url"> + :href="commitRef.ref_url" + v-tooltip + data-container="body" + :title="commitRef.name"> {{commitRef.name}} </a> @@ -153,7 +162,8 @@ :img-alt="userImageAltDescription" :tooltip-text="author.username" /> - <a class="commit-row-message" + <a + class="commit-row-message" :href="commitUrl"> {{title}} </a> diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 39c4264e496..19caefa1961 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -299,28 +299,6 @@ } } -.project-visibility-level-holder { - .radio { - margin-bottom: 10px; - - i { - margin: 2px 0; - font-size: 20px; - } - - .option-title { - font-weight: $gl-font-weight-normal; - display: inline-block; - color: $gl-text-color; - } - - .option-descr { - margin-left: 29px; - color: $project-option-descr-color; - } - } -} - .save-project-loader { margin-top: 50px; margin-bottom: 50px; diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss index 15df51e9c69..41a6ba2023a 100644 --- a/app/assets/stylesheets/pages/settings.scss +++ b/app/assets/stylesheets/pages/settings.scss @@ -143,6 +143,47 @@ } } +.visibility-level-setting { + .radio { + margin-bottom: 10px; + + i.fa { + margin: 2px 0; + font-size: 20px; + } + + .option-title { + font-weight: $gl-font-weight-normal; + display: inline-block; + color: $gl-text-color; + } + + .option-description, + .option-disabled-reason { + margin-left: 29px; + color: $project-option-descr-color; + } + + .option-disabled-reason { + display: none; + } + + &.disabled { + i.fa { + opacity: 0.5; + } + + .option-description { + display: none; + } + + .option-disabled-reason { + display: block; + } + } + } +} + .prometheus-metrics-monitoring { .panel { .panel-toggle { diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index fa1bc72560e..a99563b7100 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -117,11 +117,14 @@ class Admin::UsersController < Admin::ApplicationController user_params_with_pass = user_params.dup if params[:user][:password].present? - user_params_with_pass.merge!( + password_params = { password: params[:user][:password], - password_confirmation: params[:user][:password_confirmation], - password_expires_at: Time.now - ) + password_confirmation: params[:user][:password_confirmation] + } + + password_params[:password_expires_at] = Time.now unless changing_own_password? + + user_params_with_pass.merge!(password_params) end respond_to do |format| @@ -167,6 +170,10 @@ class Admin::UsersController < Admin::ApplicationController protected + def changing_own_password? + user == current_user + end + def user @user ||= User.find_by!(username: params[:id]) end diff --git a/app/controllers/concerns/requires_whitelisted_monitoring_client.rb b/app/controllers/concerns/requires_whitelisted_monitoring_client.rb index ad2f4bbc486..0218ac83441 100644 --- a/app/controllers/concerns/requires_whitelisted_monitoring_client.rb +++ b/app/controllers/concerns/requires_whitelisted_monitoring_client.rb @@ -1,5 +1,8 @@ module RequiresWhitelistedMonitoringClient extend ActiveSupport::Concern + + include Gitlab::CurrentSettings + included do before_action :validate_ip_whitelisted_or_valid_token! end diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index 221e01b415a..d7dd8ddcb7d 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -94,6 +94,6 @@ class Projects::ApplicationController < ApplicationController end def require_pages_enabled! - not_found unless Gitlab.config.pages.enabled + not_found unless @project.pages_available? end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 1d24563a6a6..ed17b3b4689 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -20,7 +20,10 @@ class ProjectsController < Projects::ApplicationController end def new - @project = Project.new + namespace = Namespace.find_by(id: params[:namespace_id]) if params[:namespace_id] + return access_denied! if namespace && !can?(current_user, :create_projects, namespace) + + @project = Project.new(namespace_id: namespace&.id) end def edit diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 07775a8b159..36bb7015fa1 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -202,7 +202,7 @@ module ApplicationHelper end def support_url - current_application_settings.help_page_support_url.presence || promo_url + '/getting-help/' + Gitlab::CurrentSettings.current_application_settings.help_page_support_url.presence || promo_url + '/getting-help/' end def page_filter_path(options = {}) diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 3b76da238e0..04955ed625e 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -1,5 +1,8 @@ module ApplicationSettingsHelper extend self + + include Gitlab::CurrentSettings + delegate :gravatar_enabled?, :signup_enabled?, :password_authentication_enabled?, diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb index 9c71d6c7f4c..66dc0b1e6f7 100644 --- a/app/helpers/auth_helper.rb +++ b/app/helpers/auth_helper.rb @@ -1,4 +1,6 @@ module AuthHelper + include Gitlab::CurrentSettings + PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2 authentiq).freeze FORM_BASED_PROVIDERS = [/\Aldap/, 'crowd'].freeze diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb index 7f656b8caae..d7df9bb06d2 100644 --- a/app/helpers/namespaces_helper.rb +++ b/app/helpers/namespaces_helper.rb @@ -4,7 +4,8 @@ module NamespacesHelper end def namespaces_options(selected = :current_user, display_path: false, extra_group: nil) - groups = current_user.owned_groups + current_user.masters_groups + groups = current_user.owned_groups + current_user.masters_groups + users = [current_user.namespace] unless extra_group.nil? || extra_group.is_a?(Group) extra_group = Group.find(extra_group) if Namespace.find(extra_group).kind == 'group' @@ -14,22 +15,9 @@ module NamespacesHelper groups |= [extra_group] end - users = [current_user.namespace] - - data_attr_group = { 'data-options-parent' => 'groups' } - data_attr_users = { 'data-options-parent' => 'users' } - - group_opts = [ - "Groups", groups.sort_by(&:human_name).map { |g| [display_path ? g.full_path : g.human_name, g.id, data_attr_group] } - ] - - users_opts = [ - "Users", users.sort_by(&:human_name).map { |u| [display_path ? u.path : u.human_name, u.id, data_attr_users] } - ] - options = [] - options << group_opts - options << users_opts + options << options_for_group(groups, display_path: display_path, type: 'group') + options << options_for_group(users, display_path: display_path, type: 'user') if selected == :current_user && current_user.namespace selected = current_user.namespace.id @@ -45,4 +33,23 @@ module NamespacesHelper avatar_icon(namespace.owner.email, size) end end + + private + + def options_for_group(namespaces, display_path:, type:) + group_label = type.pluralize + elements = namespaces.sort_by(&:human_name).map! do |n| + [display_path ? n.full_path : n.human_name, n.id, + data: { + options_parent: group_label, + visibility_level: n.visibility_level_value, + visibility: n.visibility, + name: n.name, + show_path: (type == 'group') ? group_path(n) : user_path(n), + edit_path: (type == 'group') ? edit_group_path(n) : nil + }] + end + + [group_label.camelize, elements] + end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index bee4950e414..c5490a2d1a8 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -1,4 +1,6 @@ module ProjectsHelper + include Gitlab::CurrentSettings + def link_to_project(project) link_to [project.namespace.becomes(Namespace), project], title: h(project.name) do title = content_tag(:span, project.name, class: 'project-name') diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb index 35755bc149b..46867d2d974 100644 --- a/app/helpers/visibility_level_helper.rb +++ b/app/helpers/visibility_level_helper.rb @@ -63,6 +63,68 @@ module VisibilityLevelHelper end end + def restricted_visibility_level_description(level) + level_name = Gitlab::VisibilityLevel.level_name(level) + "#{level_name.capitalize} visibility has been restricted by the administrator." + end + + def disallowed_visibility_level_description(level, form_model) + case form_model + when Project + disallowed_project_visibility_level_description(level, form_model) + when Group + disallowed_group_visibility_level_description(level, form_model) + end + end + + # Note: these messages closely mirror the form validation strings found in the project + # model and any changes or additons to these may also need to be made there. + def disallowed_project_visibility_level_description(level, project) + level_name = Gitlab::VisibilityLevel.level_name(level).downcase + reasons = [] + instructions = '' + + unless project.visibility_level_allowed_as_fork?(level) + reasons << "the fork source project has lower visibility" + end + + unless project.visibility_level_allowed_by_group?(level) + errors = visibility_level_errors_for_group(project.group, level_name) + + reasons << errors[:reason] + instructions << errors[:instruction] + end + + reasons = reasons.any? ? ' because ' + reasons.to_sentence : '' + "This project cannot be #{level_name}#{reasons}.#{instructions}".html_safe + end + + # Note: these messages closely mirror the form validation strings found in the group + # model and any changes or additons to these may also need to be made there. + def disallowed_group_visibility_level_description(level, group) + level_name = Gitlab::VisibilityLevel.level_name(level).downcase + reasons = [] + instructions = '' + + unless group.visibility_level_allowed_by_projects?(level) + reasons << "it contains projects with higher visibility" + end + + unless group.visibility_level_allowed_by_sub_groups?(level) + reasons << "it contains sub-groups with higher visibility" + end + + unless group.visibility_level_allowed_by_parent?(level) + errors = visibility_level_errors_for_group(group.parent, level_name) + + reasons << errors[:reason] + instructions << errors[:instruction] + end + + reasons = reasons.any? ? ' because ' + reasons.to_sentence : '' + "This group cannot be #{level_name}#{reasons}.#{instructions}".html_safe + end + def visibility_icon_description(form_model) case form_model when Project @@ -95,7 +157,18 @@ module VisibilityLevelHelper :default_group_visibility, to: :current_application_settings - def skip_level?(form_model, level) - form_model.is_a?(Project) && !form_model.visibility_level_allowed?(level) + def disallowed_visibility_level?(form_model, level) + return false unless form_model.respond_to?(:visibility_level_allowed?) + !form_model.visibility_level_allowed?(level) + end + + private + + def visibility_level_errors_for_group(group, level_name) + group_name = link_to group.name, group_path(group) + change_visiblity = link_to 'change the visibility', edit_group_path(group) + + { reason: "the visibility of #{group_name} is #{group.visibility}", + instruction: " To make this group #{level_name}, you must first #{change_visiblity} of the parent group." } end end diff --git a/app/mailers/base_mailer.rb b/app/mailers/base_mailer.rb index 654468bc7fe..8e99db444d6 100644 --- a/app/mailers/base_mailer.rb +++ b/app/mailers/base_mailer.rb @@ -1,11 +1,13 @@ class BaseMailer < ActionMailer::Base + include Gitlab::CurrentSettings + around_action :render_with_default_locale helper ApplicationHelper helper MarkupHelper attr_accessor :current_user - helper_method :current_user, :can? + helper_method :current_user, :can?, :current_application_settings default from: proc { default_sender_address.format } default reply_to: proc { default_reply_to_address.format } diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 095192e9894..8adaafe6439 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -387,7 +387,9 @@ module Ci [ { key: 'GITLAB_USER_ID', value: user.id.to_s, public: true }, - { key: 'GITLAB_USER_EMAIL', value: user.email, public: true } + { key: 'GITLAB_USER_EMAIL', value: user.email, public: true }, + { key: 'GITLAB_USER_LOGIN', value: user.username, public: true }, + { key: 'GITLAB_USER_NAME', value: user.name, public: true } ] end diff --git a/app/models/concerns/spammable.rb b/app/models/concerns/spammable.rb index f2707022a4b..731d9b9a745 100644 --- a/app/models/concerns/spammable.rb +++ b/app/models/concerns/spammable.rb @@ -28,7 +28,7 @@ module Spammable def submittable_as_spam? if user_agent_detail - user_agent_detail.submittable? && current_application_settings.akismet_enabled + user_agent_detail.submittable? && Gitlab::CurrentSettings.current_application_settings.akismet_enabled else false end diff --git a/app/models/group.rb b/app/models/group.rb index cb3ee032f69..190b27cf66b 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -26,6 +26,8 @@ class Group < Namespace validate :avatar_type, if: ->(user) { user.avatar.present? && user.avatar_changed? } validate :visibility_level_allowed_by_projects + validate :visibility_level_allowed_by_sub_groups + validate :visibility_level_allowed_by_parent validates :avatar, file_size: { maximum: 200.kilobytes.to_i } @@ -102,15 +104,24 @@ class Group < Namespace full_name end - def visibility_level_allowed_by_projects - allowed_by_projects = self.projects.where('visibility_level > ?', self.visibility_level).none? + def visibility_level_allowed_by_parent?(level = self.visibility_level) + return true unless parent_id && parent_id.nonzero? - unless allowed_by_projects - level_name = Gitlab::VisibilityLevel.level_name(visibility_level).downcase - self.errors.add(:visibility_level, "#{level_name} is not allowed since there are projects with higher visibility.") - end + level <= parent.visibility_level + end + + def visibility_level_allowed_by_projects?(level = self.visibility_level) + !projects.where('visibility_level > ?', level).exists? + end - allowed_by_projects + def visibility_level_allowed_by_sub_groups?(level = self.visibility_level) + !children.where('visibility_level > ?', level).exists? + end + + def visibility_level_allowed?(level = self.visibility_level) + visibility_level_allowed_by_parent?(level) && + visibility_level_allowed_by_projects?(level) && + visibility_level_allowed_by_sub_groups?(level) end def avatar_url(**args) @@ -275,11 +286,29 @@ class Group < Namespace list_of_ids.reverse.map { |group| variables[group.id] }.compact.flatten end - protected + private def update_two_factor_requirement return unless require_two_factor_authentication_changed? || two_factor_grace_period_changed? users.find_each(&:update_two_factor_requirement) end + + def visibility_level_allowed_by_parent + return if visibility_level_allowed_by_parent? + + errors.add(:visibility_level, "#{visibility} is not allowed since the parent group has a #{parent.visibility} visibility.") + end + + def visibility_level_allowed_by_projects + return if visibility_level_allowed_by_projects? + + errors.add(:visibility_level, "#{visibility} is not allowed since this group contains projects with higher visibility.") + end + + def visibility_level_allowed_by_sub_groups + return if visibility_level_allowed_by_sub_groups? + + errors.add(:visibility_level, "#{visibility} is not allowed since there are sub-groups with higher visibility.") + end end diff --git a/app/models/issue.rb b/app/models/issue.rb index b9aa937d2f9..dfcd4030ec3 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -269,7 +269,13 @@ class Issue < ActiveRecord::Base end end + def update_project_counter_caches? + state_changed? || confidential_changed? + end + def update_project_counter_caches + return unless update_project_counter_caches? + Projects::OpenIssuesCountService.new(project).refresh_cache end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 5be2f6d4e82..ca3a1806ee8 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -942,7 +942,13 @@ class MergeRequest < ActiveRecord::Base true end + def update_project_counter_caches? + state_changed? + end + def update_project_counter_caches + return unless update_project_counter_caches? + Projects::OpenMergeRequestsCountService.new(target_project).refresh_cache end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index e7bc1d1b080..e7cbc5170e8 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -195,6 +195,10 @@ class Namespace < ActiveRecord::Base parent.present? end + def subgroup? + has_parent? + end + def soft_delete_without_removing_associations # We can't use paranoia's `#destroy` since this will hard-delete projects. # Project uses `pending_delete` instead of the acts_as_paranoia gem. diff --git a/app/models/project.rb b/app/models/project.rb index 6c679236da6..b9247fb535a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -19,6 +19,7 @@ class Project < ActiveRecord::Base include Routable extend Gitlab::ConfigHelper + extend Gitlab::CurrentSettings BoardLimitExceeded = Class.new(StandardError) @@ -1246,6 +1247,10 @@ class Project < ActiveRecord::Base File.join(pages_path, 'public') end + def pages_available? + Gitlab.config.pages.enabled && !namespace.subgroup? + end + def remove_private_deploy_keys exclude_keys_linked_to_other_projects = <<-SQL NOT EXISTS ( diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb index 5f0d0802ac9..89bfc5f9a9c 100644 --- a/app/models/protected_branch.rb +++ b/app/models/protected_branch.rb @@ -2,6 +2,8 @@ class ProtectedBranch < ActiveRecord::Base include Gitlab::ShellAdapter include ProtectedRef + extend Gitlab::CurrentSettings + protected_ref_access_levels :merge, :push # Check if branch name is marked as protected in the system diff --git a/app/models/repository.rb b/app/models/repository.rb index d29d2a83708..b3fa51a14f7 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1044,7 +1044,7 @@ class Repository end def fetch_remote(remote, forced: false, no_tags: false) - gitlab_shell.fetch_remote(repository_storage_path, disk_path, remote, forced: forced, no_tags: no_tags) + gitlab_shell.fetch_remote(raw_repository, remote, forced: forced, no_tags: no_tags) end def fetch_ref(source_path, source_ref, target_ref) diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 09d5ff46618..9533aa7f555 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -10,6 +10,8 @@ class Snippet < ActiveRecord::Base include Spammable include Editable + extend Gitlab::CurrentSettings + cache_markdown_field :title, pipeline: :single_line cache_markdown_field :description cache_markdown_field :content diff --git a/app/models/user.rb b/app/models/user.rb index 70787de4b40..78e7c750c3b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2,6 +2,7 @@ require 'carrierwave/orm/activerecord' class User < ActiveRecord::Base extend Gitlab::ConfigHelper + extend Gitlab::CurrentSettings include Gitlab::ConfigHelper include Gitlab::CurrentSettings diff --git a/app/policies/base_policy.rb b/app/policies/base_policy.rb index a605a3457c8..8fa7b2753c7 100644 --- a/app/policies/base_policy.rb +++ b/app/policies/base_policy.rb @@ -1,8 +1,6 @@ require_dependency 'declarative_policy' class BasePolicy < DeclarativePolicy::Base - include Gitlab::CurrentSettings - desc "User is an instance admin" with_options scope: :user, score: 0 condition(:admin) { @user&.admin? } @@ -15,6 +13,6 @@ class BasePolicy < DeclarativePolicy::Base desc "The application is restricted from public visibility" condition(:restricted_public_level, scope: :global) do - current_application_settings.restricted_visibility_levels.include?(Gitlab::VisibilityLevel::PUBLIC) + Gitlab::CurrentSettings.current_application_settings.restricted_visibility_levels.include?(Gitlab::VisibilityLevel::PUBLIC) end end diff --git a/app/services/akismet_service.rb b/app/services/akismet_service.rb index 7b5482b3cd1..aa6f0e841c9 100644 --- a/app/services/akismet_service.rb +++ b/app/services/akismet_service.rb @@ -1,4 +1,6 @@ class AkismetService + include Gitlab::CurrentSettings + attr_accessor :owner, :text, :options def initialize(owner, text, options = {}) diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb index 7dae5880931..9a636346899 100644 --- a/app/services/auth/container_registry_authentication_service.rb +++ b/app/services/auth/container_registry_authentication_service.rb @@ -1,6 +1,6 @@ module Auth class ContainerRegistryAuthenticationService < BaseService - include Gitlab::CurrentSettings + extend Gitlab::CurrentSettings AUDIENCE = 'container_registry'.freeze diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb index 394b336a638..f6b83a2f621 100644 --- a/app/services/projects/update_pages_service.rb +++ b/app/services/projects/update_pages_service.rb @@ -1,5 +1,7 @@ module Projects class UpdatePagesService < BaseService + include Gitlab::CurrentSettings + BLOCK_SIZE = 32.kilobytes MAX_SIZE = 1.terabyte SITE_PATH = 'public/'.freeze diff --git a/app/services/upload_service.rb b/app/services/upload_service.rb index 6c5b2baff41..76700dfcdee 100644 --- a/app/services/upload_service.rb +++ b/app/services/upload_service.rb @@ -1,4 +1,6 @@ class UploadService + include Gitlab::CurrentSettings + def initialize(model, file, uploader_class = FileUploader) @model, @file, @uploader_class = model, file, uploader_class end diff --git a/app/services/users/build_service.rb b/app/services/users/build_service.rb index ff234a3440f..6f05500adea 100644 --- a/app/services/users/build_service.rb +++ b/app/services/users/build_service.rb @@ -1,5 +1,7 @@ module Users class BuildService < BaseService + include Gitlab::CurrentSettings + def initialize(current_user, params = {}) @current_user = current_user @params = params.dup diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 959af5c0d13..734a08c61fa 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -7,15 +7,15 @@ = f.label :default_branch_protection, class: 'control-label col-sm-2' .col-sm-10 = f.select :default_branch_protection, options_for_select(Gitlab::Access.protection_options, @application_setting.default_branch_protection), {}, class: 'form-control' - .form-group.project-visibility-level-holder + .form-group.visibility-level-setting = f.label :default_project_visibility, class: 'control-label col-sm-2' .col-sm-10 = render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: Project.new) - .form-group.project-visibility-level-holder + .form-group.visibility-level-setting = f.label :default_snippet_visibility, class: 'control-label col-sm-2' .col-sm-10 = render('shared/visibility_radios', model_method: :default_snippet_visibility, form: f, selected_level: @application_setting.default_snippet_visibility, form_model: ProjectSnippet.new) - .form-group.project-visibility-level-holder + .form-group.visibility-level-setting = f.label :default_group_visibility, class: 'control-label col-sm-2' .col-sm-10 = render('shared/visibility_radios', model_method: :default_group_visibility, form: f, selected_level: @application_setting.default_group_visibility, form_model: Group.new) diff --git a/app/views/layouts/nav/_new_project_sidebar.html.haml b/app/views/layouts/nav/_new_project_sidebar.html.haml index 53dbf9e2f2b..f5361c7af0c 100644 --- a/app/views/layouts/nav/_new_project_sidebar.html.haml +++ b/app/views/layouts/nav/_new_project_sidebar.html.haml @@ -208,7 +208,7 @@ = link_to project_settings_ci_cd_path(@project), title: 'CI / CD' do %span CI / CD - - if Gitlab.config.pages.enabled + - if @project.pages_available? = nav_link(controller: :pages) do = link_to project_pages_path(@project), title: 'Pages' do %span diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 5698bb281b4..adffd67029a 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -112,7 +112,7 @@ %span.light (optional) = f.text_area :description, placeholder: 'Description format', class: "form-control", rows: 3, maxlength: 250 - .form-group.project-visibility-level-holder + .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' } diff --git a/app/views/projects/settings/_head.html.haml b/app/views/projects/settings/_head.html.haml index 15ba09b10ba..7d24c6a9122 100644 --- a/app/views/projects/settings/_head.html.haml +++ b/app/views/projects/settings/_head.html.haml @@ -23,7 +23,7 @@ = link_to project_settings_ci_cd_path(@project), title: 'Pipelines' do %span Pipelines - - if Gitlab.config.pages.enabled + - if @project.pages_available? = nav_link(controller: :pages) do = link_to project_pages_path(@project), title: 'Pages' do %span diff --git a/app/views/shared/_visibility_level.html.haml b/app/views/shared/_visibility_level.html.haml index 73efec88bb1..192d2502aaf 100644 --- a/app/views/shared/_visibility_level.html.haml +++ b/app/views/shared/_visibility_level.html.haml @@ -1,6 +1,6 @@ - with_label = local_assigns.fetch(:with_label, true) -.form-group.project-visibility-level-holder +.form-group.visibility-level-setting - if with_label = f.label :visibility_level, class: 'control-label' do Visibility Level diff --git a/app/views/shared/_visibility_radios.html.haml b/app/views/shared/_visibility_radios.html.haml index 182c4eebd50..0ec7677a566 100644 --- a/app/views/shared/_visibility_radios.html.haml +++ b/app/views/shared/_visibility_radios.html.haml @@ -1,15 +1,17 @@ - Gitlab::VisibilityLevel.values.each do |level| - - next if skip_level?(form_model, level) - .radio - - restricted = restricted_visibility_levels.include?(level) + - disallowed = disallowed_visibility_level?(form_model, level) + - restricted = restricted_visibility_levels.include?(level) + - disabled = disallowed || restricted + .radio{ class: [('disabled' if disabled), ('restricted' if restricted)] } = form.label "#{model_method}_#{level}" do - = form.radio_button model_method, level, checked: (selected_level == level), disabled: restricted + = form.radio_button model_method, level, checked: (selected_level == level), disabled: disabled = visibility_level_icon(level) .option-title = visibility_level_label(level) - .option-descr + .option-description = visibility_level_description(level, form_model) -- unless restricted_visibility_levels.empty? - %div - %span.info - Some visibility level settings have been restricted by the administrator. + .option-disabled-reason + - if restricted + = restricted_visibility_level_description(level) + - elsif disallowed + = disallowed_visibility_level_description(level, form_model) |