# 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] 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)