Commit 74a18bd8 authored by Ramya Authappan's avatar Ramya Authappan

Merge branch 'qa-shl-user-api-to-create-pat' into 'master'

Enable PAT resource to use the admin PAT creation API

See merge request gitlab-org/gitlab!53739
parents d4638e5d df345bf7
...@@ -52,7 +52,7 @@ module QA ...@@ -52,7 +52,7 @@ module QA
using_wait_time 0 do using_wait_time 0 do
set_initial_password_if_present set_initial_password_if_present
raise NotImplementedError if Runtime::User.ldap_user? && user&.credentials_given? raise 'If an LDAP user is provided, it must be used for sign-in', QA::Resource::User::InvalidUserError if Runtime::User.ldap_user? && user && user.username != Runtime::User.ldap_username
if Runtime::User.ldap_user? if Runtime::User.ldap_user?
sign_in_using_ldap_credentials(user: user || Runtime::User) sign_in_using_ldap_credentials(user: user || Runtime::User)
......
...@@ -4,17 +4,59 @@ require 'date' ...@@ -4,17 +4,59 @@ require 'date'
module QA module QA
module Resource module Resource
##
# Create a personal access token that can be used by the api
#
class PersonalAccessToken < Base class PersonalAccessToken < Base
attr_accessor :name attr_accessor :name
attribute :access_token do # The user for which the personal access token is to be created
# This *could* be different than the api_client.user or the api_user provided by the QA::Resource::ApiFabricator module
attr_writer :user
attribute :token do
Page::Profile::PersonalAccessTokens.perform(&:created_access_token) Page::Profile::PersonalAccessTokens.perform(&:created_access_token)
end end
# Only Admins can create PAT via the API.
# If Runtime::Env.admin_personal_access_token is provided, fabricate via the API,
# else, fabricate via the browser.
def fabricate_via_api!
if Runtime::Env.admin_personal_access_token && !@user.nil?
self.api_client = Runtime::API::Client.as_admin
super
else
fabricate!
end
end
# When a user is not provided, use default user
def user
@user || Resource::User.default
end
def api_post_path
"/users/#{user.api_resource[:id]}/personal_access_tokens"
end
def api_get_path
'/personal_access_tokens'
end
def api_post_body
{
name: name || 'api-test-token',
scopes: ["api"]
}
end
def resource_web_url(resource)
super
rescue ResourceURLMissingError
# this particular resource does not expose a web_url property
end
def fabricate! def fabricate!
Flow::Login.sign_in_unless_signed_in(as: user)
Page::Main::Menu.perform(&:click_edit_profile_link) Page::Main::Menu.perform(&:click_edit_profile_link)
Page::Profile::Menu.perform(&:click_access_tokens) Page::Profile::Menu.perform(&:click_access_tokens)
......
...@@ -5,6 +5,8 @@ require 'securerandom' ...@@ -5,6 +5,8 @@ require 'securerandom'
module QA module QA
module Resource module Resource
class User < Base class User < Base
InvalidUserError = Class.new(RuntimeError)
attr_reader :unique_id attr_reader :unique_id
attr_writer :username, :password attr_writer :username, :password
attr_accessor :admin, :provider, :extern_uid, :expect_fabrication_success attr_accessor :admin, :provider, :extern_uid, :expect_fabrication_success
...@@ -21,6 +23,13 @@ module QA ...@@ -21,6 +23,13 @@ module QA
@expect_fabrication_success = true @expect_fabrication_success = true
end end
def self.default
Resource::User.new.tap 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? def admin?
api_resource&.dig(:is_admin) || false api_resource&.dig(:is_admin) || false
end end
...@@ -28,10 +37,12 @@ module QA ...@@ -28,10 +37,12 @@ module QA
def username def username
@username || "qa-user-#{unique_id}" @username || "qa-user-#{unique_id}"
end end
alias_method :ldap_username, :username
def password def password
@password || 'password' @password || 'password'
end end
alias_method :ldap_password, :password
def name def name
@name ||= api_resource&.dig(:name) || "QA User #{unique_id}" @name ||= api_resource&.dig(:name) || "QA User #{unique_id}"
...@@ -138,8 +149,8 @@ module QA ...@@ -138,8 +149,8 @@ module QA
return {} unless extern_uid && provider return {} unless extern_uid && provider
{ {
extern_uid: extern_uid, extern_uid: extern_uid,
provider: provider provider: provider
} }
end end
......
...@@ -23,22 +23,30 @@ module QA ...@@ -23,22 +23,30 @@ module QA
# unless a specific user has been passed # unless a specific user has been passed
@user.nil? ? Runtime::Env.personal_access_token ||= create_personal_access_token : create_personal_access_token @user.nil? ? Runtime::Env.personal_access_token ||= create_personal_access_token : create_personal_access_token
end end
if @user&.admin?
Runtime::Env.admin_personal_access_token = @personal_access_token
end
@personal_access_token
end end
def self.as_admin def self.as_admin
if Runtime::Env.admin_personal_access_token @admin_client ||= begin
Runtime::API::Client.new(:gitlab, personal_access_token: Runtime::Env.admin_personal_access_token) if Runtime::Env.admin_personal_access_token
else Runtime::API::Client.new(:gitlab, personal_access_token: Runtime::Env.admin_personal_access_token)
user = Resource::User.fabricate_via_api! do |user| else
user.username = Runtime::User.admin_username user = Resource::User.fabricate_via_api! do |user|
user.password = Runtime::User.admin_password user.username = Runtime::User.admin_username
user.password = Runtime::User.admin_password
end
unless user.admin?
raise AuthorizationError, "User '#{user.username}' is not an administrator."
end
Runtime::API::Client.new(:gitlab, user: user)
end end
unless user.admin?
raise AuthorizationError, "User '#{user.username}' is not an administrator."
end
Runtime::API::Client.new(:gitlab, user: user)
end end
end end
...@@ -67,9 +75,9 @@ module QA ...@@ -67,9 +75,9 @@ module QA
Page::Main::Menu.perform(&:sign_out) if @is_new_session && signed_in_initially Page::Main::Menu.perform(&:sign_out) if @is_new_session && signed_in_initially
Flow::Login.sign_in_unless_signed_in(as: @user) token = Resource::PersonalAccessToken.fabricate! do |pat|
pat.user = user
token = Resource::PersonalAccessToken.fabricate!.access_token end.token
# If this is a new session, that tests that follow could fail if they # If this is a new session, that tests that follow could fail if they
# try to sign in without starting a new session. # try to sign in without starting a new session.
......
...@@ -8,7 +8,7 @@ module QA ...@@ -8,7 +8,7 @@ module QA
module Env module Env
extend self extend self
attr_writer :personal_access_token attr_writer :personal_access_token, :admin_personal_access_token
ENV_VARIABLES = Gitlab::QA::Runtime::Env::ENV_VARIABLES ENV_VARIABLES = Gitlab::QA::Runtime::Env::ENV_VARIABLES
...@@ -78,18 +78,6 @@ module QA ...@@ -78,18 +78,6 @@ module QA
ENV['QA_PRAEFECT_REPOSITORY_STORAGE'] ENV['QA_PRAEFECT_REPOSITORY_STORAGE']
end end
def admin_password
ENV['GITLAB_ADMIN_PASSWORD']
end
def admin_username
ENV['GITLAB_ADMIN_USERNAME']
end
def admin_personal_access_token
ENV['GITLAB_QA_ADMIN_ACCESS_TOKEN']
end
def ci_job_url def ci_job_url
ENV['CI_JOB_URL'] ENV['CI_JOB_URL']
end end
...@@ -140,6 +128,18 @@ module QA ...@@ -140,6 +128,18 @@ module QA
enabled?(ENV['SIGNUP_DISABLED'], default: false) enabled?(ENV['SIGNUP_DISABLED'], default: false)
end end
def admin_password
ENV['GITLAB_ADMIN_PASSWORD']
end
def admin_username
ENV['GITLAB_ADMIN_USERNAME']
end
def admin_personal_access_token
@admin_personal_access_token ||= ENV['GITLAB_QA_ADMIN_ACCESS_TOKEN']
end
# specifies token that can be used for the api # specifies token that can be used for the api
def personal_access_token def personal_access_token
@personal_access_token ||= ENV['GITLAB_QA_ACCESS_TOKEN'] @personal_access_token ||= ENV['GITLAB_QA_ACCESS_TOKEN']
......
...@@ -23,6 +23,7 @@ module QA ...@@ -23,6 +23,7 @@ module QA
@personal_access_token = Runtime::Env.personal_access_token @personal_access_token = Runtime::Env.personal_access_token
Runtime::Env.personal_access_token = nil Runtime::Env.personal_access_token = nil
ldap_username = Runtime::Env.ldap_username ldap_username = Runtime::Env.ldap_username
Runtime::Env.ldap_username = nil Runtime::Env.ldap_username = nil
......
...@@ -107,7 +107,7 @@ module QA ...@@ -107,7 +107,7 @@ module QA
def fabricate_personal_access_token def fabricate_personal_access_token
login_to_gitlab login_to_gitlab
token = Resource::PersonalAccessToken.fabricate!.access_token token = Resource::PersonalAccessToken.fabricate!.token
Page::Main::Menu.perform(&:sign_out) Page::Main::Menu.perform(&:sign_out)
token token
end end
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
module QA module QA
RSpec.describe 'Create' do RSpec.describe 'Create' do
describe 'Git clone over HTTP', :ldap_no_tls do describe 'Git clone over HTTP' do
let(:project) do let(:project) do
Resource::Project.fabricate_via_api! do |scenario| Resource::Project.fabricate_via_api! do |scenario|
scenario.name = 'project-with-code' scenario.name = 'project-with-code'
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
module QA module QA
RSpec.describe 'Create' do RSpec.describe 'Create' do
describe 'Git push over HTTP', :ldap_no_tls, :smoke do describe 'Git push over HTTP', :smoke do
it 'user using a personal access token pushes code to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1278' do it 'user using a personal access token pushes code to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1278' do
Flow::Login.sign_in Flow::Login.sign_in
access_token = Resource::PersonalAccessToken.fabricate!.access_token access_token = Resource::PersonalAccessToken.fabricate!.token
user = Resource::User.new.tap do |user| user = Resource::User.new.tap do |user|
user.username = Runtime::User.username user.username = Runtime::User.username
......
...@@ -17,7 +17,7 @@ module QA ...@@ -17,7 +17,7 @@ module QA
p.initialize_with_readme = true p.initialize_with_readme = true
end end
@api_client = Runtime::API::Client.new(:gitlab, personal_access_token: Runtime::Env.admin_personal_access_token) @api_client = Runtime::API::Client.as_admin
end end
after(:context) do after(:context) do
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
module QA module QA
RSpec.describe 'Create' do RSpec.describe 'Create' do
describe 'Git push over HTTP', :ldap_no_tls do describe 'Git push over HTTP' do
it 'user pushes code to the repository', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1702' do it 'user pushes code to the repository', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1702' do
Flow::Login.sign_in Flow::Login.sign_in
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
module QA module QA
RSpec.describe 'Create' do RSpec.describe 'Create' do
describe 'Protected branch support', :ldap_no_tls do describe 'Protected branch support' do
let(:branch_name) { 'protected-branch' } let(:branch_name) { 'protected-branch' }
let(:commit_message) { 'Protected push commit message' } let(:commit_message) { 'Protected push commit message' }
let(:project) do let(:project) do
......
...@@ -13,7 +13,7 @@ module QA ...@@ -13,7 +13,7 @@ module QA
Flow::Login.sign_in Flow::Login.sign_in
end end
Resource::PersonalAccessToken.fabricate!.access_token Resource::PersonalAccessToken.fabricate!.token
end end
let(:project) do let(:project) do
......
...@@ -15,7 +15,7 @@ module QA ...@@ -15,7 +15,7 @@ module QA
Flow::Login.sign_in Flow::Login.sign_in
end end
Resource::PersonalAccessToken.fabricate!.access_token Resource::PersonalAccessToken.fabricate!.token
end end
let(:project) do let(:project) do
......
...@@ -12,7 +12,7 @@ module QA ...@@ -12,7 +12,7 @@ module QA
Flow::Login.sign_in Flow::Login.sign_in
end end
Resource::PersonalAccessToken.fabricate!.access_token Resource::PersonalAccessToken.fabricate!.token
end end
let(:project) do let(:project) do
......
...@@ -35,11 +35,7 @@ module QA ...@@ -35,11 +35,7 @@ module QA
] ]
before(:all) do before(:all) do
admin = QA::Resource::User.new.tap do |user| @api_client = Runtime::API::Client.as_admin
user.username = QA::Runtime::User.admin_username
user.password = QA::Runtime::User.admin_password
end
@api_client = Runtime::API::Client.new(:gitlab, user: admin)
@api_client.personal_access_token @api_client.personal_access_token
@group = Resource::Group.fabricate_via_api! do |group| @group = Resource::Group.fabricate_via_api! do |group|
......
...@@ -34,7 +34,7 @@ module QA ...@@ -34,7 +34,7 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login) Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_admin_credentials) Page::Main::Login.perform(&:sign_in_using_admin_credentials)
Runtime::Env.personal_access_token = Resource::PersonalAccessToken.fabricate!.access_token Runtime::Env.personal_access_token = Resource::PersonalAccessToken.fabricate!.token
Page::Main::Menu.perform(&:sign_out) Page::Main::Menu.perform(&:sign_out)
end end
......
...@@ -19,7 +19,7 @@ module QA ...@@ -19,7 +19,7 @@ module QA
@saml_idp_service = Flow::Saml.run_saml_idp_service(@group.path) @saml_idp_service = Flow::Saml.run_saml_idp_service(@group.path)
@api_client = Runtime::API::Client.new(:gitlab, personal_access_token: Runtime::Env.admin_personal_access_token) @api_client = Runtime::API::Client.as_admin
@developer_user = Resource::User.fabricate_via_api! @developer_user = Resource::User.fabricate_via_api!
......
...@@ -13,7 +13,7 @@ module QA ...@@ -13,7 +13,7 @@ module QA
Flow::Login.sign_in Flow::Login.sign_in
end end
Resource::PersonalAccessToken.fabricate!.access_token Resource::PersonalAccessToken.fabricate!.token
end end
let(:project) do let(:project) do
......
...@@ -21,7 +21,7 @@ module QA ...@@ -21,7 +21,7 @@ module QA
let(:auth_token) do let(:auth_token) do
QA::Flow::Login.while_signed_in(address: :geo_primary) do QA::Flow::Login.while_signed_in(address: :geo_primary) do
Resource::PersonalAccessToken.fabricate!.access_token Resource::PersonalAccessToken.fabricate!.token
end end
end end
......
...@@ -23,7 +23,7 @@ module QA ...@@ -23,7 +23,7 @@ module QA
Flow::Login.sign_in Flow::Login.sign_in
puts "Creating an API scoped access token for the root user..." puts "Creating an API scoped access token for the root user..."
puts "Token: #{Resource::PersonalAccessToken.fabricate!.access_token}" puts "Token: #{Resource::PersonalAccessToken.fabricate!.token}"
end end
end end
end end
......
...@@ -60,7 +60,7 @@ RSpec.describe QA::Runtime::API::Client do ...@@ -60,7 +60,7 @@ RSpec.describe QA::Runtime::API::Client do
end end
it 'returns a created token' do it 'returns a created token' do
client = described_class.new(user: { username: 'foo' }) client = described_class.new(user: Struct.new(:username, :admin?).new('foo', false))
expect(client).to receive(:create_personal_access_token).and_return('created_token') expect(client).to receive(:create_personal_access_token).and_return('created_token')
......
...@@ -232,6 +232,7 @@ RSpec.describe QA::Runtime::Env do ...@@ -232,6 +232,7 @@ RSpec.describe QA::Runtime::Env do
describe '.require_admin_access_token!' do describe '.require_admin_access_token!' do
it 'raises ArgumentError if GITLAB_QA_ADMIN_ACCESS_TOKEN is not specified' do it 'raises ArgumentError if GITLAB_QA_ADMIN_ACCESS_TOKEN is not specified' do
described_class.instance_variable_set(:@admin_personal_access_token, nil)
stub_env('GITLAB_QA_ADMIN_ACCESS_TOKEN', nil) stub_env('GITLAB_QA_ADMIN_ACCESS_TOKEN', nil)
expect { described_class.require_admin_access_token! }.to raise_error(ArgumentError) expect { described_class.require_admin_access_token! }.to raise_error(ArgumentError)
......
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