summaryrefslogtreecommitdiff
path: root/app/models/user.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/user.rb')
-rw-r--r--app/models/user.rb112
1 files changed, 42 insertions, 70 deletions
diff --git a/app/models/user.rb b/app/models/user.rb
index 80b8c9173d1..cb0f15c04cb 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -26,6 +26,7 @@ class User < ApplicationRecord
include UpdateHighestRole
include HasUserType
include Gitlab::Auth::Otp::Fortinet
+ include RestrictedSignup
DEFAULT_NOTIFICATION_LEVEL = :participating
@@ -205,11 +206,14 @@ class User < ApplicationRecord
has_one :user_canonical_email
has_one :credit_card_validation, class_name: '::Users::CreditCardValidation'
has_one :atlassian_identity, class_name: 'Atlassian::Identity'
+ has_one :banned_user, class_name: '::Users::BannedUser'
has_many :reviews, foreign_key: :author_id, inverse_of: :author
has_many :in_product_marketing_emails, class_name: '::Users::InProductMarketingEmail'
+ has_many :timelogs
+
#
# Validations
#
@@ -220,7 +224,7 @@ class User < ApplicationRecord
validates :email, confirmation: true
validates :notification_email, presence: true
validates :notification_email, devise_email: true, if: ->(user) { user.notification_email != user.email }
- validates :public_email, presence: true, uniqueness: true, devise_email: true, allow_blank: true
+ validates :public_email, uniqueness: true, devise_email: true, allow_blank: true
validates :commit_email, devise_email: true, allow_nil: true, if: ->(user) { user.commit_email != user.email }
validates :projects_limit,
presence: true,
@@ -231,11 +235,10 @@ class User < ApplicationRecord
validate :namespace_move_dir_allowed, if: :username_changed?
validate :unique_email, if: :email_changed?
- validate :owns_notification_email, if: :notification_email_changed?
- validate :owns_public_email, if: :public_email_changed?
- validate :owns_commit_email, if: :commit_email_changed?
- validate :signup_domain_valid?, on: :create, if: ->(user) { !user.created_by_id }
- validate :check_email_restrictions, on: :create, if: ->(user) { !user.created_by_id }
+ validate :notification_email_verified, if: :notification_email_changed?
+ validate :public_email_verified, if: :public_email_changed?
+ validate :commit_email_verified, if: :commit_email_changed?
+ validate :signup_email_valid?, on: :create, if: ->(user) { !user.created_by_id }
validate :check_username_format, if: :username_changed?
validates :theme_id, allow_nil: true, inclusion: { in: Gitlab::Themes.valid_ids,
@@ -245,7 +248,6 @@ class User < ApplicationRecord
message: _("%{placeholder} is not a valid color scheme") % { placeholder: '%{value}' } }
before_validation :sanitize_attrs
- before_validation :set_notification_email, if: :new_record?
before_validation :set_public_email, if: :public_email_changed?
before_validation :set_commit_email, if: :commit_email_changed?
before_save :default_private_profile_to_false
@@ -270,11 +272,6 @@ class User < ApplicationRecord
update_emails_with_primary_email(previous_confirmed_at, previous_email)
update_invalid_gpg_signatures
-
- if previous_email == notification_email
- self.notification_email = email
- save
- end
end
end
@@ -315,6 +312,7 @@ class User < ApplicationRecord
delegate :bio, :bio=, :bio_html, to: :user_detail, allow_nil: true
delegate :webauthn_xid, :webauthn_xid=, to: :user_detail, allow_nil: true
delegate :pronouns, :pronouns=, to: :user_detail, allow_nil: true
+ delegate :pronunciation, :pronunciation=, to: :user_detail, allow_nil: true
accepts_nested_attributes_for :user_preference, update_only: true
accepts_nested_attributes_for :user_detail, update_only: true
@@ -326,7 +324,6 @@ class User < ApplicationRecord
transition deactivated: :blocked
transition ldap_blocked: :blocked
transition blocked_pending_approval: :blocked
- transition banned: :blocked
end
event :ldap_block do
@@ -380,6 +377,14 @@ class User < ApplicationRecord
NotificationService.new.user_deactivated(user.name, user.notification_email)
end
# rubocop: enable CodeReuse/ServiceClass
+
+ after_transition active: :banned do |user|
+ user.create_banned_user
+ end
+
+ after_transition banned: :active do |user|
+ user.banned_user&.destroy
+ end
end
# Scopes
@@ -917,22 +922,22 @@ class User < ApplicationRecord
end
end
- def owns_notification_email
- return if new_record? || temp_oauth_email?
+ def notification_email_verified
+ return if read_attribute(:notification_email).blank? || temp_oauth_email?
- errors.add(:notification_email, _("is not an email you own")) unless verified_emails.include?(notification_email)
+ errors.add(:notification_email, _("must be an email you have verified")) unless verified_emails.include?(notification_email)
end
- def owns_public_email
+ def public_email_verified
return if public_email.blank?
- errors.add(:public_email, _("is not an email you own")) unless verified_emails.include?(public_email)
+ errors.add(:public_email, _("must be an email you have verified")) unless verified_emails.include?(public_email)
end
- def owns_commit_email
+ def commit_email_verified
return if read_attribute(:commit_email).blank?
- errors.add(:commit_email, _("is not an email you own")) unless verified_emails.include?(commit_email)
+ errors.add(:commit_email, _("must be an email you have verified")) unless verified_emails.include?(commit_email)
end
# Define commit_email-related attribute methods explicitly instead of relying
@@ -959,6 +964,11 @@ class User < ApplicationRecord
has_attribute?(:commit_email) && super
end
+ def notification_email
+ # The notification email is the same as the primary email if undefined
+ super.presence || self.email
+ end
+
def private_commit_email
Gitlab::PrivateCommitEmail.for_user(self)
end
@@ -1005,6 +1015,8 @@ class User < ApplicationRecord
# Returns a relation of groups the user has access to, including their parent
# and child groups (recursively).
def all_expanded_groups
+ return groups if groups.empty?
+
Gitlab::ObjectHierarchy.new(groups).all_objects
end
@@ -1576,10 +1588,11 @@ class User < ApplicationRecord
.order('routes.path')
end
- def namespaces
- namespace_ids = groups.pluck(:id)
- namespace_ids.push(namespace.id)
- Namespace.where(id: namespace_ids)
+ def namespaces(owned_only: false)
+ user_groups = owned_only ? owned_groups : groups
+ personal_namespace = Namespace.where(id: namespace.id)
+
+ Namespace.from_union([user_groups, personal_namespace])
end
def oauth_authorized_tokens
@@ -2008,8 +2021,8 @@ class User < ApplicationRecord
def authorized_groups_without_shared_membership
Group.from_union([
- groups,
- authorized_projects.joins(:namespace).select('namespaces.*')
+ groups.select(Namespace.arel_table[Arel.star]),
+ authorized_projects.joins(:namespace).select(Namespace.arel_table[Arel.star])
])
end
@@ -2058,51 +2071,10 @@ class User < ApplicationRecord
end
end
- def signup_domain_valid?
- valid = true
- error = nil
-
- if Gitlab::CurrentSettings.domain_denylist_enabled?
- blocked_domains = Gitlab::CurrentSettings.domain_denylist
- if domain_matches?(blocked_domains, email)
- error = 'is not from an allowed domain.'
- valid = false
- end
- end
-
- allowed_domains = Gitlab::CurrentSettings.domain_allowlist
- unless allowed_domains.blank?
- if domain_matches?(allowed_domains, email)
- valid = true
- else
- error = "domain is not authorized for sign-up"
- valid = false
- end
- end
-
- errors.add(:email, error) unless valid
-
- valid
- end
-
- def domain_matches?(email_domains, email)
- signup_domain = Mail::Address.new(email).domain
- email_domains.any? do |domain|
- escaped = Regexp.escape(domain).gsub('\*', '.*?')
- regexp = Regexp.new "^#{escaped}$", Regexp::IGNORECASE
- signup_domain =~ regexp
- end
- end
+ def signup_email_valid?
+ error = validate_admin_signup_restrictions(email)
- def check_email_restrictions
- return unless Gitlab::CurrentSettings.email_restrictions_enabled?
-
- restrictions = Gitlab::CurrentSettings.email_restrictions
- return if restrictions.blank?
-
- if Gitlab::UntrustedRegexp.new(restrictions).match?(email)
- errors.add(:email, _('is not allowed. Try again with a different email address, or contact your GitLab admin.'))
- end
+ errors.add(:email, error) if error
end
def check_username_format