Skip to content

Commit 119926c

Browse files
Merge pull request #1761 from atlassian/fix-for-locust-confluence-login-as-app-specific
Fix for locust confluence login as app specific
2 parents 7008458 + b4c650b commit 119926c

File tree

1 file changed

+119
-54
lines changed

1 file changed

+119
-54
lines changed

app/locustio/common_utils.py

Lines changed: 119 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,18 @@
7373
'atl_token': '',
7474
'login': 'Log in'
7575
}
76+
LOGIN_BODY_CONFLUENCE = {
77+
'os_username': '',
78+
'os_password': '',
79+
'os_cookie': True,
80+
'os_destination': '',
81+
'login': 'Log in'
82+
}
7683

7784
JIRA_TOKEN_PATTERN = r'name="atlassian-token" content="(.+?)">'
7885
CONFLUENCE_TOKEN_PATTERN = r'"ajs-atl-token" content="(.+?)"'
86+
CONFLUENCE_KEYBOARD_HASH_RE = 'name=\"ajs-keyboardshortcut-hash\" content=\"(.*?)\">'
87+
CONFLUENCE_BUILD_NUMBER_RE = 'meta name=\"ajs-build-number\" content=\"(.*?)\"'
7988

8089
JIRA = 'jira'
8190
JSM = 'jsm'
@@ -349,6 +358,105 @@ def raise_if_login_failed(locust):
349358
raise exception.StopUser('Action login_and_view_dashboard failed')
350359

351360

361+
def do_confluence_login(locust, usr, pwd):
362+
locust.client.cookies.clear()
363+
r = locust.get('/dologin.action', catch_response=True)
364+
content = r.content.decode('utf-8')
365+
is_legacy_login_form = 'loginform' in content
366+
367+
if is_legacy_login_form:
368+
369+
login_body = LOGIN_BODY_CONFLUENCE
370+
login_body['os_username'] = usr
371+
login_body['os_password'] = pwd
372+
373+
locust.post('/dologin.action',
374+
login_body,
375+
TEXT_HEADERS,
376+
catch_response=True)
377+
else:
378+
379+
login_body = {'username': usr,
380+
'password': pwd,
381+
'rememberMe': 'True',
382+
'targetUrl': ''
383+
}
384+
385+
headers = {
386+
"Content-Type": "application/json"
387+
}
388+
389+
# 15 /rest/tsv/1.0/authenticate
390+
locust.post('/rest/tsv/1.0/authenticate',
391+
json=login_body,
392+
headers=headers,
393+
catch_response=True)
394+
r = locust.get(url='/', catch_response=True)
395+
content = r.content.decode('utf-8')
396+
397+
if 'Log Out' not in content:
398+
print(f'Login with {usr}, {pwd} failed: {content}')
399+
assert 'Log Out' in content, 'User authentication failed.'
400+
print(f'User {usr} is successfully logged in back')
401+
keyboard_hash = fetch_by_re(CONFLUENCE_KEYBOARD_HASH_RE, content)
402+
build_number = fetch_by_re(CONFLUENCE_BUILD_NUMBER_RE, content)
403+
token = fetch_by_re(locust.session_data_storage['token_pattern'], content)
404+
405+
# 20 index.action
406+
locust.get('/index.action', catch_response=True)
407+
408+
locust.session_data_storage['build_number'] = build_number
409+
locust.session_data_storage['keyboard_hash'] = keyboard_hash
410+
locust.session_data_storage['username'] = usr
411+
locust.session_data_storage['password'] = pwd
412+
locust.session_data_storage['token'] = token
413+
414+
415+
def do_login_jira(locust, usr, pwd):
416+
locust.client.cookies.clear()
417+
body = LOGIN_BODY
418+
body['os_username'] = usr
419+
body['os_password'] = pwd
420+
421+
legacy_form = False
422+
423+
# Check if 2sv login form
424+
r = locust.get('/login.jsp', catch_response=True)
425+
content = r.content.decode('utf-8')
426+
if 'login-form-remember-me' in content:
427+
legacy_form = True
428+
429+
# 100 /login.jsp
430+
if legacy_form:
431+
locust.post('/login.jsp', body,
432+
TEXT_HEADERS,
433+
catch_response=True)
434+
else:
435+
login_body = {'username': usr,
436+
'password': pwd,
437+
'rememberMe': 'True',
438+
'targetUrl': ''
439+
}
440+
441+
headers = {
442+
"Content-Type": "application/json"
443+
}
444+
445+
# 15 /rest/tsv/1.0/authenticate
446+
locust.post('/rest/tsv/1.0/authenticate',
447+
json=login_body,
448+
headers=headers,
449+
catch_response=True)
450+
451+
r = locust.get('/', catch_response=True)
452+
if not r.content:
453+
raise Exception('Please check server hostname in jira.yml file')
454+
if locust.session_data_storage['token_pattern']:
455+
content = r.content.decode('utf-8')
456+
token = fetch_by_re(locust.session_data_storage['token_pattern'], content)
457+
locust.session_data_storage["token"] = token
458+
459+
352460
def run_as_specific_user(username=None, password=None):
353461
if not (username and password):
354462
raise SystemExit(f'The credentials are not valid: {{username: {username}, password: {password}}}.')
@@ -367,72 +475,29 @@ def wrapper(*args, **kwargs):
367475
session_user_name = locust.session_data_storage["username"]
368476
session_user_password = locust.session_data_storage["password"]
369477
app = locust.session_data_storage['app']
478+
locust.session_data_storage['token_pattern'] = None
370479
app_type = locust.session_data_storage.get('app_type', None)
371480
token_pattern = None
372481

373482
# Jira or JSM Agent - redefine token value
374483
if app == JIRA or (app == JSM and app_type == TYPE_AGENT):
375-
token_pattern = JIRA_TOKEN_PATTERN
484+
locust.session_data_storage['token_pattern'] = JIRA_TOKEN_PATTERN
376485
# Confluence - redefine token value
377486
elif app == CONFLUENCE:
378-
token_pattern = CONFLUENCE_TOKEN_PATTERN
379-
380-
def do_login_jira(usr, pwd):
381-
locust.client.cookies.clear()
382-
body = LOGIN_BODY
383-
body['os_username'] = usr
384-
body['os_password'] = pwd
385-
386-
legacy_form = False
387-
388-
# Check if 2sv login form
389-
r = locust.get('/login.jsp', catch_response=True)
390-
content = r.content.decode('utf-8')
391-
if 'login-form-remember-me' in content:
392-
legacy_form = True
393-
394-
# 100 /login.jsp
395-
if legacy_form:
396-
locust.post('/login.jsp', body,
397-
TEXT_HEADERS,
398-
catch_response=True)
399-
else:
400-
login_body = {'username': usr,
401-
'password': pwd,
402-
'rememberMe': 'True',
403-
'targetUrl': ''
404-
}
405-
406-
headers = {
407-
"Content-Type": "application/json"
408-
}
409-
410-
# 15 /rest/tsv/1.0/authenticate
411-
locust.post('/rest/tsv/1.0/authenticate',
412-
json=login_body,
413-
headers=headers,
414-
catch_response=True)
415-
416-
r = locust.get('/', catch_response=True)
417-
if not r.content:
418-
raise Exception('Please check server hostname in jira.yml file')
419-
if token_pattern:
420-
content = r.content.decode('utf-8')
421-
token = fetch_by_re(token_pattern, content)
422-
locust.session_data_storage["token"] = token
487+
locust.session_data_storage['token_pattern'] = CONFLUENCE_TOKEN_PATTERN
423488

424489
# send requests by the specific user
425490
if app == JIRA or (app == JSM and app_type == TYPE_AGENT):
426-
do_login_jira(usr=username, pwd=password)
427-
else:
428-
raise SystemExit(f"Unsupported app type: {app}")
491+
do_login_jira(locust, username, password)
492+
func(*args, **kwargs)
493+
do_login_jira(locust, session_user_name, session_user_password)
429494

430-
func(*args, **kwargs)
495+
if app == CONFLUENCE:
496+
do_confluence_login(locust, username, password)
497+
func(*args, **kwargs)
498+
do_confluence_login(locust, session_user_name, session_user_password)
431499

432-
# send requests by the session user
433-
if app == JIRA or (app == JSM and app_type == TYPE_AGENT):
434-
do_login_jira(usr=session_user_name, pwd=session_user_password)
435-
else:
500+
if app not in [CONFLUENCE, JIRA, JSM]:
436501
raise SystemExit(f"Unsupported app type: {app}")
437502

438503
else:

0 commit comments

Comments
 (0)