Commit 57f864fa authored by Peter Leitzen's avatar Peter Leitzen

Merge branch 'task_bot' into 'master'

Introduce Project bot user

See merge request gitlab-org/gitlab!28169
parents 37952697 fc7a89c4
......@@ -337,7 +337,8 @@ class User < ApplicationRecord
scope :with_dashboard, -> (dashboard) { where(dashboard: dashboard) }
scope :with_public_profile, -> { where(private_profile: false) }
scope :bots, -> { where(user_type: UserTypeEnums.bots.values) }
scope :not_bots, -> { humans.or(where.not(user_type: UserTypeEnums.bots.values)) }
scope :bots_without_project_bot, -> { bots.where.not(user_type: UserTypeEnums.bots[:project_bot]) }
scope :with_project_bots, -> { humans.or(where.not(user_type: UserTypeEnums.bots.except(:project_bot).values)) }
scope :humans, -> { where(user_type: nil) }
scope :with_expiring_and_not_notified_personal_access_tokens, ->(at) do
......@@ -657,8 +658,10 @@ class User < ApplicationRecord
UserTypeEnums.bots.has_key?(user_type)
end
# The explicit check for project_bot will be removed with Bot Categorization
# Ref: https://gitlab.com/gitlab-org/gitlab/-/issues/213945
def internal?
ghost? || bot?
ghost? || (bot? && !project_bot?)
end
# We are transitioning from ghost boolean column to user_type
......@@ -668,12 +671,16 @@ class User < ApplicationRecord
ghost
end
# The explicit check for project_bot will be removed with Bot Categorization
# Ref: https://gitlab.com/gitlab-org/gitlab/-/issues/213945
def self.internal
where(ghost: true).or(bots)
where(ghost: true).or(bots_without_project_bot)
end
# The explicit check for project_bot will be removed with Bot Categorization
# Ref: https://gitlab.com/gitlab-org/gitlab/-/issues/213945
def self.non_internal
without_ghosts.not_bots
without_ghosts.with_project_bots
end
#
......
......@@ -6,7 +6,7 @@ module UserTypeEnums
end
def self.bots
@bots ||= { alert_bot: 2 }.with_indifferent_access
@bots ||= { alert_bot: 2, project_bot: 6 }.with_indifferent_access
end
end
......
......@@ -17,6 +17,8 @@ class GlobalPolicy < BasePolicy
condition(:private_instance_statistics, score: 0) { Gitlab::CurrentSettings.instance_statistics_visibility_private? }
condition(:project_bot, scope: :user) { @user&.project_bot? }
rule { admin | (~private_instance_statistics & ~anonymous) }
.enable :read_instance_statistics
......@@ -51,6 +53,11 @@ class GlobalPolicy < BasePolicy
prevent :use_slash_commands
end
rule { project_bot }.policy do
prevent :log_in
prevent :receive_notifications
end
rule { deactivated }.policy do
prevent :access_git
prevent :access_api
......
......@@ -262,6 +262,7 @@ module EE
def using_license_seat?
active? &&
!internal? &&
!project_bot? &&
has_current_license? &&
paid_in_current_license?
end
......
......@@ -27,6 +27,10 @@ FactoryBot.define do
user_type { :alert_bot }
end
trait :project_bot do
user_type { :project_bot }
end
trait :external do
external { true }
end
......
......@@ -4357,18 +4357,19 @@ describe User, :do_not_mock_admin_mode do
describe 'internal methods' do
let_it_be(:user) { create(:user) }
let!(:ghost) { described_class.ghost }
let!(:alert_bot) { described_class.alert_bot }
let!(:non_internal) { [user] }
let!(:internal) { [ghost, alert_bot] }
let_it_be(:ghost) { described_class.ghost }
let_it_be(:alert_bot) { described_class.alert_bot }
let_it_be(:project_bot) { create(:user, :project_bot) }
let_it_be(:non_internal) { [user, project_bot] }
let_it_be(:internal) { [ghost, alert_bot] }
it 'returns internal users' do
expect(described_class.internal).to eq(internal)
expect(described_class.internal).to match_array(internal)
expect(internal.all?(&:internal?)).to eq(true)
end
it 'returns non internal users' do
expect(described_class.non_internal).to eq(non_internal)
expect(described_class.non_internal).to match_array(non_internal)
expect(non_internal.all?(&:internal?)).to eq(false)
end
......@@ -4420,9 +4421,12 @@ describe User, :do_not_mock_admin_mode do
it 'returns corresponding users' do
human = create(:user)
bot = create(:user, :bot)
project_bot = create(:user, :project_bot)
expect(described_class.humans).to match_array([human])
expect(described_class.bots).to match_array([bot])
expect(described_class.bots).to match_array([bot, project_bot])
expect(described_class.bots_without_project_bot).to match_array([bot])
expect(described_class.with_project_bots).to match_array([human, project_bot])
end
end
......
# frozen_string_literal: true
require 'spec_helper'
describe UserTypeEnums do
it '.types' do
expect(described_class.types.keys).to include('alert_bot', 'project_bot', 'human', 'ghost')
end
it '.bots' do
expect(described_class.bots.keys).to include('alert_bot', 'project_bot')
end
end
......@@ -5,6 +5,7 @@ require 'spec_helper'
describe GlobalPolicy do
include TermsHelper
let_it_be(:project_bot) { create(:user, :project_bot) }
let(:current_user) { create(:user) }
let(:user) { create(:user) }
......@@ -120,6 +121,12 @@ describe GlobalPolicy do
it { is_expected.to be_allowed(:access_api) }
end
context 'project bot' do
let(:current_user) { project_bot }
it { is_expected.to be_allowed(:access_api) }
end
context 'when terms are enforced' do
before do
enforce_terms
......@@ -203,6 +210,12 @@ describe GlobalPolicy do
it { is_expected.not_to be_allowed(:receive_notifications) }
end
context 'project bot' do
let(:current_user) { project_bot }
it { is_expected.not_to be_allowed(:receive_notifications) }
end
end
describe 'git access' do
......@@ -265,6 +278,12 @@ describe GlobalPolicy do
it { is_expected.to be_allowed(:access_git) }
end
end
context 'project bot' do
let(:current_user) { project_bot }
it { is_expected.to be_allowed(:access_git) }
end
end
describe 'read instance metadata' do
......@@ -361,6 +380,12 @@ describe GlobalPolicy do
it { is_expected.not_to be_allowed(:use_slash_commands) }
end
context 'project bot' do
let(:current_user) { project_bot }
it { is_expected.to be_allowed(:use_slash_commands) }
end
end
describe 'create_snippet' do
......@@ -380,4 +405,12 @@ describe GlobalPolicy do
it { is_expected.not_to be_allowed(:create_snippet) }
end
end
describe 'log in' do
context 'project bot' do
let(:current_user) { project_bot }
it { is_expected.not_to be_allowed(:log_in) }
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment