gitlab-org--gitlab-foss/qa/qa/resource/user.rb

237 lines
6.3 KiB
Ruby

# frozen_string_literal: true
module QA
module Resource
class User < Base
InvalidUserError = Class.new(RuntimeError)
attr_reader :unique_id
attr_writer :username, :password
attr_accessor :admin,
:provider,
:extern_uid,
:expect_fabrication_success,
:hard_delete_on_api_removal,
:access_level
attributes :id,
:name,
:first_name,
:last_name,
:email
def initialize
@admin = false
@hard_delete_on_api_removal = false
@unique_id = SecureRandom.hex(8)
@expect_fabrication_success = true
end
def self.default
Resource::User.init do |user|
user.username = Runtime::User.ldap_user? ? Runtime::User.ldap_username : Runtime::User.username
user.password = Runtime::User.ldap_user? ? Runtime::User.ldap_password : Runtime::User.password
end
end
def admin?
api_resource&.dig(:is_admin) || false
end
def username
@username || "qa-user-#{unique_id}"
end
alias_method :ldap_username, :username
def password
@password ||= "Pa$$w0rd"
end
alias_method :ldap_password, :password
def name
@name ||= api_resource&.dig(:name) || "QA User #{unique_id}"
end
def first_name
name.split(' ').first
end
def last_name
name.split(' ').drop(1).join(' ')
end
def email
@email ||= begin
api_email = api_resource&.dig(:email)
api_email && !api_email.empty? ? api_email : "#{username}@example.com"
end
end
def public_email
@public_email ||= begin
api_public_email = api_resource&.dig(:public_email)
api_public_email && !api_public_email.empty? ? api_public_email : Runtime::User.default_email
end
end
def credentials_given?
defined?(@username) && defined?(@password)
end
def fabricate!
# Don't try to log-out if we're not logged-in
Page::Main::Menu.perform(&:sign_out) if Page::Main::Menu.perform { |p| p.has_personal_area?(wait: 0) }
if credentials_given?
Page::Main::Login.perform do |login|
login.sign_in_using_credentials(user: self)
end
else
Flow::SignUp.sign_up!(self)
end
end
def fabricate_via_api!
resource_web_url(api_get)
rescue ResourceNotFoundError
super
end
def exists?
api_get
rescue ResourceNotFoundError
false
end
def api_delete_path
"/users/#{id}?hard_delete=#{hard_delete_on_api_removal}"
rescue NoValueError
"/users/#{fetch_id(username)}?hard_delete=#{hard_delete_on_api_removal}"
end
def api_get_path
return "/user" if fetching_own_data?
"/users/#{fetch_id(username)}"
end
def api_post_path
'/users'
end
def api_put_path
"/users/#{id}"
end
def api_block_path
"/users/#{id}/block"
end
def api_approve_path
"/users/#{id}/approve"
end
def api_post_body
{
admin: admin,
email: email,
password: password,
username: username,
name: name,
skip_confirmation: true
}.merge(ldap_post_body)
end
def self.fabricate_or_use(username = nil, password = nil)
if Runtime::Env.signup_disabled?
fabricate_via_api! do |user|
user.username = username
user.password = password
end
else
fabricate! do |user|
user.username = username if username
user.password = password if password
end
end
end
# Get users from the API
#
# @param [Integer] per_page the number of pages to traverse (used for pagination)
# @return [Array<Hash>] parsed response body
def self.all(per_page: 100)
response = nil
Resource::User.init do |user|
response = user.get(Runtime::API::Request.new(Runtime::API::Client.as_admin,
'/users',
per_page: per_page.to_s).url)
raise ResourceQueryError unless response.code == 200
end.parse_body(response)
end
def approve!
response = post(Runtime::API::Request.new(api_client, api_approve_path).url, nil)
return if response.code == 201
raise ResourceUpdateFailedError, "Failed to approve user. Request returned (#{response.code}): `#{response}`"
end
def block!
response = post(Runtime::API::Request.new(api_client, api_block_path).url, nil)
return if response.code == HTTP_STATUS_CREATED
raise ResourceUpdateFailedError, "Failed to block user. Request returned (#{response.code}): `#{response}`."
end
def set_public_email
response = put(Runtime::API::Request.new(api_client, api_put_path).url, { public_email: email })
return if response.code == HTTP_STATUS_OK
raise(
ResourceUpdateFailedError,
"Failed to set public email. Request returned (#{response.code}): `#{response}`."
)
end
protected
# Compare users by username and password
#
# @return [Array]
def comparable
[username, password]
end
private
def ldap_post_body
return {} unless extern_uid && provider
{
extern_uid: extern_uid,
provider: provider
}
end
def fetch_id(username)
users = parse_body(api_get_from("/users?username=#{username}"))
unless users.size == 1 && users.first[:username] == username
raise ResourceNotFoundError, "Expected one user with username #{username} but found: `#{users}`."
end
users.first[:id]
end
def fetching_own_data?
runtime_username = Runtime::User.ldap_user? ? Runtime::User.ldap_username : Runtime::User.username
api_user&.username == username || runtime_username == username
end
end
end
end
QA::Resource::User.prepend_mod_with('Resource::User', namespace: QA)