Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/user.rb')
-rw-r--r--app/models/user.rb76
1 files changed, 55 insertions, 21 deletions
diff --git a/app/models/user.rb b/app/models/user.rb
index 11046bdabe4..507e8cc2cf5 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -103,6 +103,8 @@ class User < ApplicationRecord
# Profile
has_many :keys, -> { regular_keys }, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :expired_today_and_unnotified_keys, -> { expired_today_and_not_notified }, class_name: 'Key'
+ has_many :expiring_soon_and_unnotified_keys, -> { expiring_soon_and_not_notified }, class_name: 'Key'
has_many :deploy_keys, -> { where(type: 'DeployKey') }, dependent: :nullify # rubocop:disable Cop/ActiveRecordDependent
has_many :group_deploy_keys
has_many :gpg_keys
@@ -125,7 +127,7 @@ class User < ApplicationRecord
# Groups
has_many :members
- has_many :group_members, -> { where(requested_at: nil).where("access_level >= ?", Gitlab::Access::GUEST) }, source: 'GroupMember'
+ has_many :group_members, -> { where(requested_at: nil).where("access_level >= ?", Gitlab::Access::GUEST) }, class_name: 'GroupMember'
has_many :groups, through: :group_members
has_many :owned_groups, -> { where(members: { access_level: Gitlab::Access::OWNER }) }, through: :group_members, source: :group
has_many :maintainers_groups, -> { where(members: { access_level: Gitlab::Access::MAINTAINER }) }, through: :group_members, source: :group
@@ -139,7 +141,7 @@ class User < ApplicationRecord
-> { where(members: { access_level: [Gitlab::Access::REPORTER, Gitlab::Access::DEVELOPER, Gitlab::Access::MAINTAINER, Gitlab::Access::OWNER] }) },
through: :group_members,
source: :group
- has_many :minimal_access_group_members, -> { where(access_level: [Gitlab::Access::MINIMAL_ACCESS]) }, source: 'GroupMember', class_name: 'GroupMember'
+ has_many :minimal_access_group_members, -> { where(access_level: [Gitlab::Access::MINIMAL_ACCESS]) }, class_name: 'GroupMember'
has_many :minimal_access_groups, through: :minimal_access_group_members, source: :group
# Projects
@@ -199,6 +201,8 @@ class User < ApplicationRecord
has_many :reviews, foreign_key: :author_id, inverse_of: :author
+ has_many :in_product_marketing_emails, class_name: '::Users::InProductMarketingEmail'
+
#
# Validations
#
@@ -350,7 +354,8 @@ class User < ApplicationRecord
# this state transition object in order to do a rollback.
# For this reason the tradeoff is to disable this cop.
after_transition any => :blocked do |user|
- Ci::CancelUserPipelinesService.new.execute(user)
+ Ci::DropPipelineService.new.execute_async_for_all(user.pipelines, :user_blocked, user)
+ Ci::DisableUserPipelineSchedulesService.new.execute(user)
end
# rubocop: enable CodeReuse/ServiceClass
end
@@ -390,6 +395,22 @@ class User < ApplicationRecord
.without_impersonation
.expired_today_and_not_notified)
end
+ scope :with_ssh_key_expired_today, -> do
+ includes(:expired_today_and_unnotified_keys)
+ .where('EXISTS (?)',
+ ::Key
+ .select(1)
+ .where('keys.user_id = users.id')
+ .expired_today_and_not_notified)
+ end
+ scope :with_ssh_key_expiring_soon, -> do
+ includes(:expiring_soon_and_unnotified_keys)
+ .where('EXISTS (?)',
+ ::Key
+ .select(1)
+ .where('keys.user_id = users.id')
+ .expiring_soon_and_not_notified)
+ end
scope :order_recent_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'DESC')) }
scope :order_oldest_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'ASC')) }
scope :order_recent_last_activity, -> { reorder(Gitlab::Database.nulls_last_order('last_activity_on', 'DESC')) }
@@ -743,6 +764,7 @@ class User < ApplicationRecord
u.bio = 'The GitLab support bot used for Service Desk'
u.name = 'GitLab Support Bot'
u.avatar = bot_avatar(image: 'support-bot.png')
+ u.confirmed_at = Time.zone.now
end
end
@@ -1024,7 +1046,7 @@ class User < ApplicationRecord
[
Project.where(namespace: namespace),
Project.joins(:project_authorizations)
- .where("projects.namespace_id <> ?", namespace.id)
+ .where.not('projects.namespace_id' => namespace.id)
.where(project_authorizations: { user_id: id, access_level: Gitlab::Access::OWNER })
],
remove_duplicates: false
@@ -1337,9 +1359,11 @@ class User < ApplicationRecord
end
def public_verified_emails
- emails = verified_emails(include_private_email: false)
- emails << email unless temp_oauth_email?
- emails.uniq
+ strong_memoize(:public_verified_emails) do
+ emails = verified_emails(include_private_email: false)
+ emails << email unless temp_oauth_email?
+ emails.uniq
+ end
end
def any_email?(check_email)
@@ -1595,32 +1619,40 @@ class User < ApplicationRecord
@global_notification_setting
end
+ def count_cache_validity_period
+ if Feature.enabled?(:longer_count_cache_validity, self, default_enabled: :yaml)
+ 24.hours
+ else
+ 20.minutes
+ end
+ end
+
def assigned_open_merge_requests_count(force: false)
- Rails.cache.fetch(['users', id, 'assigned_open_merge_requests_count'], force: force, expires_in: 20.minutes) do
+ Rails.cache.fetch(['users', id, 'assigned_open_merge_requests_count'], force: force, expires_in: count_cache_validity_period) do
MergeRequestsFinder.new(self, assignee_id: self.id, state: 'opened', non_archived: true).execute.count
end
end
def review_requested_open_merge_requests_count(force: false)
- Rails.cache.fetch(['users', id, 'review_requested_open_merge_requests_count'], force: force, expires_in: 20.minutes) do
+ Rails.cache.fetch(['users', id, 'review_requested_open_merge_requests_count'], force: force, expires_in: count_cache_validity_period) do
MergeRequestsFinder.new(self, reviewer_id: id, state: 'opened', non_archived: true).execute.count
end
end
def assigned_open_issues_count(force: false)
- Rails.cache.fetch(['users', id, 'assigned_open_issues_count'], force: force, expires_in: 20.minutes) do
+ Rails.cache.fetch(['users', id, 'assigned_open_issues_count'], force: force, expires_in: count_cache_validity_period) do
IssuesFinder.new(self, assignee_id: self.id, state: 'opened', non_archived: true).execute.count
end
end
def todos_done_count(force: false)
- Rails.cache.fetch(['users', id, 'todos_done_count'], force: force, expires_in: 20.minutes) do
+ Rails.cache.fetch(['users', id, 'todos_done_count'], force: force, expires_in: count_cache_validity_period) do
TodosFinder.new(self, state: :done).execute.count
end
end
def todos_pending_count(force: false)
- Rails.cache.fetch(['users', id, 'todos_pending_count'], force: force, expires_in: 20.minutes) do
+ Rails.cache.fetch(['users', id, 'todos_pending_count'], force: force, expires_in: count_cache_validity_period) do
TodosFinder.new(self, state: :pending).execute.count
end
end
@@ -1639,8 +1671,7 @@ class User < ApplicationRecord
def invalidate_cache_counts
invalidate_issue_cache_counts
invalidate_merge_request_cache_counts
- invalidate_todos_done_count
- invalidate_todos_pending_count
+ invalidate_todos_cache_counts
invalidate_personal_projects_count
end
@@ -1653,11 +1684,8 @@ class User < ApplicationRecord
Rails.cache.delete(['users', id, 'review_requested_open_merge_requests_count'])
end
- def invalidate_todos_done_count
+ def invalidate_todos_cache_counts
Rails.cache.delete(['users', id, 'todos_done_count'])
- end
-
- def invalidate_todos_pending_count
Rails.cache.delete(['users', id, 'todos_pending_count'])
end
@@ -1835,10 +1863,12 @@ class User < ApplicationRecord
end
def dismissed_callout?(feature_name:, ignore_dismissal_earlier_than: nil)
- callouts = self.callouts.with_feature_name(feature_name)
- callouts = callouts.with_dismissed_after(ignore_dismissal_earlier_than) if ignore_dismissal_earlier_than
+ callout = callouts_by_feature_name[feature_name]
+
+ return false unless callout
+ return callout.dismissed_after?(ignore_dismissal_earlier_than) if ignore_dismissal_earlier_than
- callouts.any?
+ true
end
# Load the current highest access by looking directly at the user's memberships
@@ -1901,6 +1931,10 @@ class User < ApplicationRecord
private
+ def callouts_by_feature_name
+ @callouts_by_feature_name ||= callouts.index_by(&:feature_name)
+ end
+
def authorized_groups_without_shared_membership
Group.from_union([
groups,