diff options
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/appearance.rb | 1 | ||||
-rw-r--r-- | app/models/ci/pipeline.rb | 16 | ||||
-rw-r--r-- | app/models/commit_status.rb | 10 | ||||
-rw-r--r-- | app/models/concerns/enum_with_nil.rb | 33 | ||||
-rw-r--r-- | app/models/group.rb | 20 | ||||
-rw-r--r-- | app/models/list.rb | 18 | ||||
-rw-r--r-- | app/models/merge_request.rb | 5 | ||||
-rw-r--r-- | app/models/notification_recipient.rb | 31 | ||||
-rw-r--r-- | app/models/project_auto_devops.rb | 31 | ||||
-rw-r--r-- | app/models/project_services/jira_service.rb | 2 | ||||
-rw-r--r-- | app/models/user.rb | 5 |
11 files changed, 141 insertions, 31 deletions
diff --git a/app/models/appearance.rb b/app/models/appearance.rb index 67cc84a9140..b770aadef0e 100644 --- a/app/models/appearance.rb +++ b/app/models/appearance.rb @@ -14,6 +14,7 @@ class Appearance < ActiveRecord::Base mount_uploader :logo, AttachmentUploader mount_uploader :header_logo, AttachmentUploader + mount_uploader :favicon, FaviconUploader # Overrides CacheableAttributes.current_without_cache def self.current_without_cache diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index eecd86349e4..0878356e87a 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -8,6 +8,7 @@ module Ci include Gitlab::OptimisticLocking include Gitlab::Utils::StrongMemoize include AtomicInternalId + include EnumWithNil belongs_to :project, inverse_of: :pipelines belongs_to :user @@ -54,7 +55,7 @@ module Ci after_create :keep_around_commits, unless: :importing? - enum source: { + enum_with_nil source: { unknown: nil, push: 1, web: 2, @@ -64,7 +65,7 @@ module Ci external: 6 } - enum config_source: { + enum_with_nil config_source: { unknown_source: nil, repository_source: 1, auto_devops_source: 2 @@ -599,17 +600,6 @@ module Ci @latest_builds_with_artifacts ||= builds.latest.with_artifacts_archive.to_a end - # Rails 5.0 autogenerated question mark enum methods return wrong result if enum value is nil. - # They always return `false`. - # These methods overwrite autogenerated ones to return correct results. - def unknown? - Gitlab.rails5? ? source.nil? : super - end - - def unknown_source? - Gitlab.rails5? ? config_source.nil? : super - end - private def ci_yaml_from_repo diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index a7d05722287..97516079b66 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -3,6 +3,7 @@ class CommitStatus < ActiveRecord::Base include Importable include AfterCommitQueue include Presentable + include EnumWithNil self.table_name = 'ci_builds' @@ -39,7 +40,7 @@ class CommitStatus < ActiveRecord::Base scope :retried_ordered, -> { retried.ordered.includes(project: :namespace) } scope :after_stage, -> (index) { where('stage_idx > ?', index) } - enum failure_reason: { + enum_with_nil failure_reason: { unknown_failure: nil, script_failure: 1, api_failure: 2, @@ -190,11 +191,4 @@ class CommitStatus < ActiveRecord::Base v =~ /\d+/ ? v.to_i : v end end - - # Rails 5.0 autogenerated question mark enum methods return wrong result if enum value is nil. - # They always return `false`. - # This method overwrites the autogenerated one to return correct result. - def unknown_failure? - Gitlab.rails5? ? failure_reason.nil? : super - end end diff --git a/app/models/concerns/enum_with_nil.rb b/app/models/concerns/enum_with_nil.rb new file mode 100644 index 00000000000..6b37903da20 --- /dev/null +++ b/app/models/concerns/enum_with_nil.rb @@ -0,0 +1,33 @@ +module EnumWithNil + extend ActiveSupport::Concern + + included do + def self.enum_with_nil(definitions) + # use original `enum` to auto-define all methods + enum(definitions) + + # override auto-defined methods only for the + # key which uses nil value + definitions.each do |name, values| + next unless key_with_nil = values.key(nil) + + # E.g. for enum_with_nil failure_reason: { unknown_failure: nil } + # this overrides auto-generated method `unknown_failure?` + define_method("#{key_with_nil}?") do + Gitlab.rails5? ? self[name].nil? : super() + end + + # E.g. for enum_with_nil failure_reason: { unknown_failure: nil } + # this overrides auto-generated method `failure_reason` + define_method(name) do + orig = super() + + return orig unless Gitlab.rails5? + return orig unless orig.nil? + + self.class.public_send(name.to_s.pluralize).key(nil) # rubocop:disable GitlabSecurity/PublicSend + end + end + end + end +end diff --git a/app/models/group.rb b/app/models/group.rb index aeb50fb9bb7..9c171de7fc3 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -11,6 +11,7 @@ class Group < Namespace include GroupDescendant include TokenAuthenticatable include WithUploads + include Gitlab::Utils::StrongMemoize has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source # rubocop:disable Cop/ActiveRecordDependent alias_method :members, :group_members @@ -26,7 +27,11 @@ class Group < Namespace has_many :milestones has_many :project_group_links, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :shared_projects, through: :project_group_links, source: :project + + # Overridden on another method + # Left here just to be dependent: :destroy has_many :notification_settings, dependent: :destroy, as: :source # rubocop:disable Cop/ActiveRecordDependent + has_many :labels, class_name: 'GroupLabel' has_many :variables, class_name: 'Ci::GroupVariable' has_many :custom_attributes, class_name: 'GroupCustomAttribute' @@ -88,6 +93,15 @@ class Group < Namespace end end + # Overrides notification_settings has_many association + # This allows to apply notification settings from parent groups + # to child groups and projects. + def notification_settings + source_type = self.class.base_class.name + + NotificationSetting.where(source_type: source_type, source_id: self_and_ancestors_ids) + end + def to_reference(_from = nil, full: nil) "#{self.class.reference_prefix}#{full_path}" end @@ -225,6 +239,12 @@ class Group < Namespace members_with_parents.pluck(:user_id) end + def self_and_ancestors_ids + strong_memoize(:self_and_ancestors_ids) do + self_and_ancestors.pluck(:id) + end + end + def members_with_parents # Avoids an unnecessary SELECT when the group has no parents source_ids = diff --git a/app/models/list.rb b/app/models/list.rb index 5daf35ef845..4edcfa78835 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -2,17 +2,27 @@ class List < ActiveRecord::Base belongs_to :board belongs_to :label - enum list_type: { backlog: 0, label: 1, closed: 2 } + enum list_type: { backlog: 0, label: 1, closed: 2, assignee: 3 } validates :board, :list_type, presence: true validates :label, :position, presence: true, if: :label? validates :label_id, uniqueness: { scope: :board_id }, if: :label? - validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :label? + validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :movable? before_destroy :can_be_destroyed - scope :destroyable, -> { where(list_type: list_types[:label]) } - scope :movable, -> { where(list_type: list_types[:label]) } + scope :destroyable, -> { where(list_type: list_types.slice(*destroyable_types).values) } + scope :movable, -> { where(list_type: list_types.slice(*movable_types).values) } + + class << self + def destroyable_types + [:label] + end + + def movable_types + [:label] + end + end def destroyable? label? diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 535a2c362f2..324065c1162 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -1125,8 +1125,11 @@ class MergeRequest < ActiveRecord::Base project.merge_requests.merged.where(author_id: author_id).empty? end + # TODO: remove once production database rename completes + alias_attribute :allow_collaboration, :allow_maintainer_to_push + def allow_collaboration - collaborative_push_possible? && super + collaborative_push_possible? && allow_maintainer_to_push end alias_method :allow_collaboration?, :allow_collaboration diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb index 2c3580bbdc6..1a03dd9df56 100644 --- a/app/models/notification_recipient.rb +++ b/app/models/notification_recipient.rb @@ -1,4 +1,6 @@ class NotificationRecipient + include Gitlab::Utils::StrongMemoize + attr_reader :user, :type, :reason def initialize(user, type, **opts) unless NotificationSetting.levels.key?(type) || type == :subscription @@ -64,7 +66,7 @@ class NotificationRecipient return false unless @target return false unless @target.respond_to?(:subscriptions) - subscription = @target.subscriptions.find_by_user_id(@user.id) + subscription = @target.subscriptions.find { |subscription| subscription.user_id == @user.id } subscription && !subscription.subscribed end @@ -142,10 +144,33 @@ class NotificationRecipient return project_setting unless project_setting.nil? || project_setting.global? - group_setting = @group && user.notification_settings_for(@group) + group_setting = closest_non_global_group_notification_settting - return group_setting unless group_setting.nil? || group_setting.global? + return group_setting unless group_setting.nil? user.global_notification_setting end + + # Returns the notificaton_setting of the lowest group in hierarchy with non global level + def closest_non_global_group_notification_settting + return unless @group + return if indexed_group_notification_settings.empty? + + notification_setting = nil + + @group.self_and_ancestors_ids.each do |id| + notification_setting = indexed_group_notification_settings[id] + break if notification_setting + end + + notification_setting + end + + def indexed_group_notification_settings + strong_memoize(:indexed_group_notification_settings) do + @group.notification_settings.where(user_id: user.id) + .where.not(level: NotificationSetting.levels[:global]) + .index_by(&:source_id) + end + end end diff --git a/app/models/project_auto_devops.rb b/app/models/project_auto_devops.rb index ed6c1eddbc1..d7d6aaceb27 100644 --- a/app/models/project_auto_devops.rb +++ b/app/models/project_auto_devops.rb @@ -1,11 +1,18 @@ class ProjectAutoDevops < ActiveRecord::Base belongs_to :project + enum deploy_strategy: { + continuous: 0, + manual: 1 + } + scope :enabled, -> { where(enabled: true) } scope :disabled, -> { where(enabled: false) } validates :domain, allow_blank: true, hostname: { allow_numeric_hostname: true } + after_save :create_gitlab_deploy_token, if: :needs_to_create_deploy_token? + def instance_domain Gitlab::CurrentSettings.auto_devops_domain end @@ -20,6 +27,30 @@ class ProjectAutoDevops < ActiveRecord::Base variables.append(key: 'AUTO_DEVOPS_DOMAIN', value: domain.presence || instance_domain) end + + if manual? + variables.append(key: 'STAGING_ENABLED', value: 1) + variables.append(key: 'INCREMENTAL_ROLLOUT_ENABLED', value: 1) + end end end + + private + + def create_gitlab_deploy_token + project.deploy_tokens.create!( + name: DeployToken::GITLAB_DEPLOY_TOKEN_NAME, + read_registry: true + ) + end + + def needs_to_create_deploy_token? + auto_devops_enabled? && + !project.public? && + !project.deploy_tokens.find_by(name: DeployToken::GITLAB_DEPLOY_TOKEN_NAME).present? + end + + def auto_devops_enabled? + Gitlab::CurrentSettings.auto_devops_enabled? || enabled? + end end diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index eb3261c902f..412d62388f0 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -265,7 +265,7 @@ class JiraService < IssueTrackerService title: title, status: status, icon: { - title: 'GitLab', url16x16: asset_url('favicon.ico', host: gitlab_config.url) + title: 'GitLab', url16x16: asset_url(Gitlab::Favicon.main, host: gitlab_config.url) } } } diff --git a/app/models/user.rb b/app/models/user.rb index e219ab800ad..8e0dc91b2a7 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1038,7 +1038,10 @@ class User < ActiveRecord::Base def notification_settings_for(source) if notification_settings.loaded? - notification_settings.find { |notification| notification.source == source } + notification_settings.find do |notification| + notification.source_type == source.class.base_class.name && + notification.source_id == source.id + end else notification_settings.find_or_initialize_by(source: source) end |