Skip to content

Commit

Permalink
Merge pull request #184 from gpongelli/common_authentication
Browse files Browse the repository at this point in the history
Common authentication
  • Loading branch information
dixudx authored Mar 29, 2023
2 parents da253d2 + ac5e37d commit 9f4fdaa
Show file tree
Hide file tree
Showing 5 changed files with 287 additions and 4 deletions.
2 changes: 1 addition & 1 deletion examples/how_to/workitem/get_workitem.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
url = "https://your_domain:9443/jazz"
username = "your_username"
password = "your_password"
myclient = RTCClient(url, username, password)
myclient = RTCClient(url, username, password) # ends_with_jazz , old_rtc_authentication kwargs

# get all workitems
# If both projectarea_id and projectarea_name are None, all the workitems
Expand Down
14 changes: 13 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
]
yapf = "*"
tox = "*"
toml = "*"


[build-system]
Expand Down
24 changes: 22 additions & 2 deletions rtcclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import xmltodict

from rtcclient import exception
from rtcclient import urlparse, urlquote, OrderedDict
from rtcclient import urlencode, urlparse, urlquote, OrderedDict
from rtcclient.base import RTCBase
from rtcclient.models import FiledAgainst, FoundIn, Comment, Action, State # noqa: F401
from rtcclient.models import IncludedInBuild, ChangeSet, Attachment # noqa: F401
Expand Down Expand Up @@ -58,7 +58,8 @@ def __init__(self,
proxies=None,
searchpath=None,
ends_with_jazz=True,
verify: Union[bool, str] = False):
verify: Union[bool, str] = False,
old_rtc_authentication=False):
"""Initialization
See params above
Expand All @@ -68,6 +69,7 @@ def __init__(self,
self.password = password
self.proxies = proxies
self.verify = verify
self.old_rtc_authentication = old_rtc_authentication
RTCBase.__init__(self, url)

if not isinstance(ends_with_jazz, bool):
Expand Down Expand Up @@ -99,6 +101,24 @@ def _get_headers(self):
proxies=self.proxies,
allow_redirects=_allow_redirects)

if self.old_rtc_authentication:
# works with server that needs 0.6.0 version
_headers["Content-Type"] = self.CONTENT_URL_ENCODED
if resp.headers.get("set-cookie") is not None:
_headers["Cookie"] = resp.headers.get("set-cookie")

credentials = urlencode({
"j_username": self.username,
"j_password": self.password
})

resp = self.post(self.url + "/authenticated/j_security_check",
data=credentials,
verify=False,
headers=_headers,
proxies=self.proxies,
allow_redirects=_allow_redirects)

# authfailed
authfailed = resp.headers.get("x-com-ibm-team-repository-web-auth-msg")
if authfailed == "authfailed":
Expand Down
250 changes: 250 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import requests
import pytest
import utils_test
from unittest.mock import call

from rtcclient.project_area import ProjectArea
from rtcclient.models import Severity, Priority, FoundIn, FiledAgainst
from rtcclient.models import TeamArea, Member, PlannedFor
Expand Down Expand Up @@ -42,6 +44,254 @@ def test_headers(mocker):
assert client.headers == expected_headers


def test_client_rest_calls_new_auth(mocker):
mocked_get = mocker.patch("requests.get")
mocked_post = mocker.patch("requests.post")

mock_rsp = mocker.MagicMock(spec=requests.Response)
mock_rsp.status_code = 200

mocked_get.return_value = mock_rsp
mocked_post.return_value = mock_rsp

mock_rsp.headers = {"set-cookie": "cookie-id"}
_ = RTCClient(url="http://test.url:9443/jazz",
username="user",
password="password")

# assert GET calls
assert mocked_get.call_count == 2
mocked_get.assert_has_calls([
call('http://test.url:9443/jazz/authenticated/identity',
verify=False,
headers={
'Content-Type': 'text/xml',
'Cookie': 'cookie-id',
'Accept': 'text/xml'
},
proxies=None,
timeout=60,
auth=('user', 'password'),
allow_redirects=True),
call('http://test.url:9443/jazz/authenticated/identity',
verify=False,
headers={
'Content-Type': 'text/xml',
'Cookie': 'cookie-id',
'Accept': 'text/xml'
},
proxies=None,
timeout=60,
auth=('user', 'password'),
allow_redirects=True)
])

# assert POST calls
assert mocked_post.call_count == 0


def test_client_rest_calls_old_auth(mocker):
mocked_get = mocker.patch("requests.get")
mocked_post = mocker.patch("requests.post")

mock_rsp = mocker.MagicMock(spec=requests.Response)
mock_rsp.status_code = 200

mocked_get.return_value = mock_rsp
mocked_post.return_value = mock_rsp

mock_rsp.headers = {"set-cookie": "cookie-id"}
_ = RTCClient(url="http://test.url:9443/jazz",
username="user",
password="password",
old_rtc_authentication=True)

# assert GET calls
assert mocked_get.call_count == 2
mocked_get.assert_has_calls([
call('http://test.url:9443/jazz/authenticated/identity',
verify=False,
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': 'cookie-id',
'Accept': 'text/xml'
},
proxies=None,
timeout=60,
auth=('user', 'password'),
allow_redirects=True),
call('http://test.url:9443/jazz/authenticated/identity',
verify=False,
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': 'cookie-id',
'Accept': 'text/xml'
},
proxies=None,
timeout=60,
auth=('user', 'password'),
allow_redirects=True)
])

# assert POST calls
assert mocked_post.call_count == 1
mocked_post.assert_has_calls([
call('http://test.url:9443/jazz/authenticated/j_security_check',
data='j_username=user&j_password=password',
json=None,
verify=False,
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': 'cookie-id',
'Accept': 'text/xml'
},
proxies=None,
timeout=60,
allow_redirects=True)
])


def test_headers_auth_required_new_auth(mocker):
mocked_get = mocker.patch("requests.get")
mocked_post = mocker.patch("requests.post")

mock_rsp = mocker.MagicMock(spec=requests.Response)
mock_rsp.status_code = 200

# auth required
mock_rsp.headers = {
"set-cookie": "cookie-id",
"X-com-ibm-team-repository-web-auth-msg": "authrequired"
}

mocked_get.return_value = mock_rsp
mocked_post.return_value = mock_rsp

_ = RTCClient(url="http://test.url:9443/jazz",
username="user",
password="password")

# assert GET calls
assert mocked_get.call_count == 2
mocked_get.assert_has_calls([
call('http://test.url:9443/jazz/authenticated/identity',
verify=False,
headers={
'Content-Type': 'text/xml',
'Cookie': 'cookie-id',
'Accept': 'text/xml'
},
proxies=None,
timeout=60,
auth=('user', 'password'),
allow_redirects=True),
call('http://test.url:9443/jazz/authenticated/identity',
verify=False,
headers={
'Content-Type': 'text/xml',
'Cookie': 'cookie-id',
'Accept': 'text/xml'
},
proxies=None,
timeout=60,
auth=('user', 'password'),
allow_redirects=True)
])

# assert POST calls
assert mocked_post.call_count == 1
mocked_post.assert_has_calls([
call('http://test.url:9443/jazz/authenticated/j_security_check',
data={
'j_username': 'user',
'j_password': 'password'
},
json=None,
verify=False,
headers={'Content-Type': 'application/x-www-form-urlencoded'},
proxies=None,
timeout=60,
allow_redirects=True)
])


def test_headers_auth_required_old_auth(mocker):
mocked_get = mocker.patch("requests.get")
mocked_post = mocker.patch("requests.post")

mock_rsp = mocker.MagicMock(spec=requests.Response)
mock_rsp.status_code = 200

# auth required
mock_rsp.headers = {
"set-cookie": "cookie-id",
"X-com-ibm-team-repository-web-auth-msg": "authrequired"
}

mocked_get.return_value = mock_rsp
mocked_post.return_value = mock_rsp

_ = RTCClient(url="http://test.url:9443/jazz",
username="user",
password="password",
old_rtc_authentication=True)

# assert GET calls
assert mocked_get.call_count == 2
mocked_get.assert_has_calls([
call('http://test.url:9443/jazz/authenticated/identity',
verify=False,
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': 'cookie-id',
'Accept': 'text/xml'
},
proxies=None,
timeout=60,
auth=('user', 'password'),
allow_redirects=True),
call('http://test.url:9443/jazz/authenticated/identity',
verify=False,
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': 'cookie-id',
'Accept': 'text/xml'
},
proxies=None,
timeout=60,
auth=('user', 'password'),
allow_redirects=True)
])

# assert POST calls
assert mocked_post.call_count == 2
mocked_post.assert_has_calls([
call('http://test.url:9443/jazz/authenticated/j_security_check',
data='j_username=user&j_password=password',
json=None,
verify=False,
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': 'cookie-id',
'Accept': 'text/xml'
},
proxies=None,
timeout=60,
allow_redirects=True),
call('http://test.url:9443/jazz/authenticated/j_security_check',
data={
'j_username': 'user',
'j_password': 'password'
},
json=None,
verify=False,
headers={'Content-Type': 'application/x-www-form-urlencoded'},
proxies=None,
timeout=60,
allow_redirects=True)
])


class TestRTCClient:

@pytest.fixture(autouse=True)
Expand Down

0 comments on commit 9f4fdaa

Please sign in to comment.