189 lines
6.2 KiB
Ruby
189 lines
6.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Gitlab::Seeder::Users
|
|
include ActionView::Helpers::NumberHelper
|
|
|
|
RANDOM_USERS_COUNT = 20
|
|
MASS_NAMESPACES_COUNT = ENV['CI'] ? 1 : 100
|
|
MASS_USERS_COUNT = ENV['CI'] ? 10 : 1_000_000
|
|
attr_reader :opts
|
|
|
|
def initialize(opts = {})
|
|
@opts = opts
|
|
end
|
|
|
|
def seed!
|
|
Sidekiq::Testing.inline! do
|
|
create_mass_users!
|
|
create_mass_namespaces!
|
|
create_random_users!
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def create_mass_users!
|
|
encrypted_password = Devise::Encryptor.digest(User, random_password)
|
|
|
|
Gitlab::Seeder.with_mass_insert(MASS_USERS_COUNT, User) do
|
|
ActiveRecord::Base.connection.execute <<~SQL
|
|
INSERT INTO users (username, name, email, state, confirmed_at, projects_limit, encrypted_password)
|
|
SELECT
|
|
'#{Gitlab::Seeder::MASS_INSERT_USER_START}' || seq,
|
|
'Seed user ' || seq,
|
|
'seed_user' || seq || '@example.com',
|
|
'active',
|
|
to_timestamp(seq),
|
|
#{MASS_USERS_COUNT},
|
|
'#{encrypted_password}'
|
|
FROM generate_series(1, #{MASS_USERS_COUNT}) AS seq
|
|
ON CONFLICT DO NOTHING;
|
|
SQL
|
|
end
|
|
|
|
relation = User.where(admin: false)
|
|
Gitlab::Seeder.with_mass_insert(relation.count, 'user namespaces') do
|
|
ActiveRecord::Base.connection.execute <<~SQL
|
|
INSERT INTO namespaces (name, path, owner_id, type)
|
|
SELECT
|
|
username,
|
|
username,
|
|
id,
|
|
'User'
|
|
FROM users WHERE NOT admin
|
|
ON CONFLICT DO NOTHING;
|
|
SQL
|
|
end
|
|
|
|
Gitlab::Seeder.with_mass_insert(relation.count, "User namespaces routes") do
|
|
ActiveRecord::Base.connection.execute <<~SQL
|
|
INSERT INTO routes (namespace_id, source_id, source_type, path, name)
|
|
SELECT id as namespace_id, id as source_id, 'Namespace', path, name
|
|
FROM namespaces WHERE type IS NULL OR type = 'User'
|
|
ON CONFLICT DO NOTHING;
|
|
SQL
|
|
end
|
|
|
|
puts '==========================================================='
|
|
puts "INFO: Password for newly created users is: #{random_password}"
|
|
puts '==========================================================='
|
|
end
|
|
|
|
def create_random_users!
|
|
RANDOM_USERS_COUNT.times do |i|
|
|
begin
|
|
User.create!(
|
|
username: FFaker::Internet.user_name,
|
|
name: FFaker::Name.name,
|
|
email: FFaker::Internet.email,
|
|
confirmed_at: DateTime.now,
|
|
password: random_password
|
|
)
|
|
|
|
print '.'
|
|
rescue ActiveRecord::RecordInvalid
|
|
print 'F'
|
|
end
|
|
end
|
|
end
|
|
|
|
def create_mass_namespaces!
|
|
Gitlab::Seeder.with_mass_insert(MASS_NAMESPACES_COUNT, "root namespaces and subgroups 9 levels deep") do
|
|
ActiveRecord::Base.connection.execute <<~SQL
|
|
INSERT INTO namespaces (name, path, type)
|
|
SELECT
|
|
'mass insert group level 0 - ' || seq,
|
|
'#{Gitlab::Seeder::MASS_INSERT_GROUP_START}_0_' || seq,
|
|
'Group'
|
|
FROM generate_series(1, #{MASS_NAMESPACES_COUNT}) AS seq
|
|
ON CONFLICT DO NOTHING;
|
|
SQL
|
|
|
|
(1..9).each do |idx|
|
|
count = Namespace.where("path LIKE '#{Gitlab::Seeder::MASS_INSERT_PREFIX}%'").where(type: 'Group').count * 2
|
|
Gitlab::Seeder.log_message("Creating subgroups at level #{idx}: #{count}")
|
|
ActiveRecord::Base.connection.execute <<~SQL
|
|
INSERT INTO namespaces (name, path, type, parent_id)
|
|
SELECT
|
|
'mass insert group level #{idx} - ' || seq,
|
|
'#{Gitlab::Seeder::MASS_INSERT_GROUP_START}_#{idx}_' || seq,
|
|
'Group',
|
|
namespaces.id
|
|
FROM namespaces
|
|
CROSS JOIN generate_series(1, 2) AS seq
|
|
WHERE namespaces.type='Group' AND namespaces.path like '#{Gitlab::Seeder::MASS_INSERT_GROUP_START}_#{idx-1}_%'
|
|
ON CONFLICT DO NOTHING;
|
|
SQL
|
|
end
|
|
|
|
Gitlab::Seeder.log_message("creating routes.")
|
|
ActiveRecord::Base.connection.execute <<~SQL
|
|
WITH RECURSIVE cte(source_id, namespace_id, parent_id, path, height) AS (
|
|
(
|
|
SELECT ARRAY[batch.id], batch.id, batch.parent_id, batch.path, 1
|
|
FROM
|
|
"namespaces" as batch
|
|
WHERE
|
|
"batch"."type" = 'Group' AND "batch"."parent_id" is null
|
|
)
|
|
UNION
|
|
(
|
|
SELECT array_append(cte.source_id, n.id), n.id, n.parent_id, cte.path || '/' || n.path, cte.height+1
|
|
FROM
|
|
"namespaces" as n,
|
|
"cte"
|
|
WHERE
|
|
"n"."type" = 'Group'
|
|
AND "n"."parent_id" = "cte"."namespace_id"
|
|
)
|
|
)
|
|
INSERT INTO routes (namespace_id, source_id, source_type, path, name)
|
|
SELECT cte.namespace_id as namespace_id, cte.namespace_id as source_id, 'Namespace', cte.path, cte.path FROM cte
|
|
ON CONFLICT DO NOTHING;
|
|
SQL
|
|
|
|
Gitlab::Seeder.log_message("filling traversal ids.")
|
|
ActiveRecord::Base.connection.execute <<~SQL
|
|
WITH RECURSIVE cte(source_id, namespace_id, parent_id) AS (
|
|
(
|
|
SELECT ARRAY[batch.id], batch.id, batch.parent_id
|
|
FROM
|
|
"namespaces" as batch
|
|
WHERE
|
|
"batch"."type" = 'Group' AND "batch"."parent_id" is null
|
|
)
|
|
UNION
|
|
(
|
|
SELECT array_append(cte.source_id, n.id), n.id, n.parent_id
|
|
FROM
|
|
"namespaces" as n,
|
|
"cte"
|
|
WHERE
|
|
"n"."type" = 'Group'
|
|
AND "n"."parent_id" = "cte"."namespace_id"
|
|
)
|
|
)
|
|
UPDATE namespaces
|
|
SET traversal_ids = computed.source_id FROM (SELECT namespace_id, source_id FROM cte) AS computed
|
|
where computed.namespace_id = namespaces.id AND namespaces.path LIKE '#{Gitlab::Seeder::MASS_INSERT_PREFIX}%'
|
|
SQL
|
|
|
|
Gitlab::Seeder.log_message("creating namespace settings.")
|
|
ActiveRecord::Base.connection.execute <<~SQL
|
|
INSERT INTO namespace_settings(namespace_id, created_at, updated_at)
|
|
SELECT id, now(), now() FROM namespaces
|
|
ON CONFLICT DO NOTHING;
|
|
SQL
|
|
end
|
|
end
|
|
|
|
|
|
def random_password
|
|
@random_password ||= SecureRandom.hex.slice(0,16)
|
|
end
|
|
end
|
|
|
|
Gitlab::Seeder.quiet do
|
|
users = Gitlab::Seeder::Users.new
|
|
users.seed!
|
|
end
|