Skip to content

Commit dd1ff23

Browse files
committed
bugy#305 updated gitlab oauth tests to reflect new structure
1 parent fa3d664 commit dd1ff23

3 files changed

Lines changed: 111 additions & 208 deletions

File tree

‎src/auth/auth_gitlab.py‎

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from tornado.auth import OAuth2Mixin
44

55
from auth.auth_abstract_oauth import AbstractOauthAuthenticator, _OauthUserInfo
6-
from auth.auth_base import AuthFailureError
76

87
LOGGER = logging.getLogger('script_server.GitlabAuthorizer')
98

@@ -17,12 +16,12 @@
1716
class GitlabOAuthAuthenticator(AbstractOauthAuthenticator, OAuth2Mixin):
1817
def __init__(self, params_dict):
1918
self.gitlab_host = params_dict.get('url', 'https://gitlab.com')
20-
self.gitlab_group_support = params_dict.get('group_support', True)
19+
gitlab_group_support = params_dict.get('group_support', True)
2120

2221
super().__init__(
2322
_OAUTH_AUTHORIZE_URL % self.gitlab_host,
2423
_OAUTH_ACCESS_TOKEN_URL % self.gitlab_host,
25-
'api' if self.gitlab_group_support else 'read_user',
24+
'api' if gitlab_group_support else 'read_user',
2625
params_dict)
2726

2827
self.gitlab_group_search = params_dict.get('group_search')
@@ -62,9 +61,4 @@ async def fetch_user_groups(self, access_token):
6261
if group.get('full_path'):
6362
groups.append(group['full_path'])
6463

65-
if groups is None:
66-
error_message = 'Cant read user groups'
67-
LOGGER.error(error_message)
68-
raise AuthFailureError(error_message)
69-
7064
return groups

‎src/tests/auth/test_auth_abstract_oauth.py‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import random
44
import threading
55
import time
6-
import unittest
76
from unittest import TestCase
87
from unittest.mock import Mock, patch
98

@@ -18,9 +17,6 @@
1817
from tests.test_utils import mock_object
1918
from utils import file_utils
2019

21-
if __name__ == '__main__':
22-
unittest.main()
23-
2420
mock_time = Mock()
2521
mock_time.return_value = 10000.01
2622

‎src/tests/auth/test_auth_gitlab.py‎

Lines changed: 109 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -1,200 +1,113 @@
1-
import copy
2-
import json
3-
import os
4-
import tempfile
5-
import time
61
import unittest
2+
from unittest.mock import patch
73

8-
from tornado import escape
4+
# noinspection PyProtectedMember
5+
from tornado.testing import AsyncTestCase, gen_test
96

7+
from auth.auth_abstract_oauth import _OauthUserInfo
108
from auth.auth_gitlab import GitlabOAuthAuthenticator
11-
from model import server_conf
12-
from tests import test_utils
13-
from utils import file_utils
14-
from unittest import TestCase
15-
from unittest.mock import patch, Mock
16-
17-
if __name__ == '__main__':
18-
unittest.main()
19-
20-
mock_time = Mock()
21-
mock_time.return_value = 10000.01
22-
mock_persist_session = Mock()
23-
mock_do_update_groups = Mock()
24-
mock_do_update_user = Mock()
25-
mock_request_handler = Mock(**{'get_secure_cookie.return_value': "12345".encode()})
26-
27-
28-
class TestAuthConfig(TestCase):
29-
@patch('time.time', mock_time)
30-
@patch('auth.auth_gitlab.GitlabOAuthAuthenticator.persist_session', mock_persist_session)
31-
@patch('auth.auth_gitlab.GitlabOAuthAuthenticator.do_update_groups', mock_do_update_groups)
32-
def test_gitlab_oauth(self):
33-
now = time.time()
34-
state = {
35-
"user@test.com": {
36-
"groups": ["testgroup"],
37-
"updating": False,
38-
"updated": now-10,
39-
"visit": now-10,
40-
"id": 1,
41-
"username": "test",
42-
"name": "John",
43-
"email": "user@test.com",
44-
"state": "active"
45-
},
46-
"nogroups@test.com": {
47-
"groups": None,
48-
"updating": True,
49-
"updated": now-10,
50-
"visit": now-10,
51-
"id": 2,
52-
"username": "nogroups",
53-
"name": "John",
54-
"email": "nogroups@test.com",
55-
"state": "blocked"
56-
}
57-
}
58-
59-
state_file = test_utils.create_file("gitlab_state.json", text=escape.json_encode(state))
60-
61-
config = _from_json({
62-
'auth': {
63-
"type": "gitlab",
64-
"url": "https://gitlab",
65-
"client_id": "1234",
66-
"secret": "abcd",
67-
"group_search": "script-server",
68-
"auth_info_ttl": 80,
69-
"state_dump_file": state_file,
70-
"session_expire_minutes": 10
71-
},
72-
'access': {
73-
'allowed_users': []
74-
}})
75-
76-
self.assertIsInstance(config.authenticator, GitlabOAuthAuthenticator)
77-
self.assertEqual(state_file, config.authenticator.gitlab_dump)
78-
self.assertEqual("1234", config.authenticator._client_visible_config['client_id'])
79-
self.assertEqual("https://gitlab/oauth/authorize", config.authenticator._client_visible_config['oauth_url'])
80-
self.assertEqual("api", config.authenticator._client_visible_config['oauth_scope'])
81-
82-
assert_state = state.copy()
83-
for key in list(assert_state.keys()):
84-
assert_state[key]['updating'] = False
85-
assert_state[key]['updated'] = 10000.01 - 80 - 1
86-
self.assertDictEqual(assert_state, config.authenticator.user_states)
87-
saved_state = copy.deepcopy(config.authenticator.user_states)
88-
89-
self.assertEqual(False, config.authenticator.validate_user("unknown@test.com", mock_request_handler))
90-
self.assertEqual(False, config.authenticator.validate_user("nogroups@test.com", mock_request_handler))
91-
self.assertListEqual([], config.authenticator.get_groups("unknown@test.com"))
92-
self.assertListEqual([], config.authenticator.get_groups("nogroups@test.com"))
93-
94-
self.assertEqual(True, config.authenticator.validate_user("user@test.com", mock_request_handler))
95-
self.assertEqual(time.time(), config.authenticator.user_states["user@test.com"]["visit"], "visit updated")
96-
self.assertEqual(True, mock_do_update_groups.called, "state just loaded, gitlab updating")
97-
mock_do_update_groups.reset_mock()
98-
99-
config.authenticator.user_states["user@test.com"]["updating"] = True
100-
self.assertEqual(True, config.authenticator.validate_user("user@test.com", mock_request_handler))
101-
self.assertEqual(False, mock_do_update_groups.called, "do not call parallel updated")
102-
mock_do_update_groups.reset_mock()
103-
104-
mock_time.return_value = 10000.01 + 80*2 + 1 # stale request
105-
self.assertEqual(True, config.authenticator.validate_user("user@test.com", mock_request_handler))
106-
self.assertEqual(True, mock_do_update_groups.called, "parallel but stale")
107-
mock_do_update_groups.reset_mock()
108-
config.authenticator.user_states = copy.deepcopy(saved_state)
109-
mock_time.return_value = 10000.01
110-
111-
config.authenticator.user_states["user@test.com"]['updated'] = now # gitlab info updated
112-
config.authenticator.user_states["user@test.com"]['updating'] = False
113-
self.assertEqual(True, config.authenticator.validate_user("user@test.com", mock_request_handler))
114-
self.assertEqual(False, mock_do_update_groups.called, "do not update gitlab because ttl not expired")
115-
mock_do_update_groups.reset_mock()
116-
117-
mock_time.return_value = 10000.01 + 81
118-
self.assertEqual(True, config.authenticator.validate_user("user@test.com", mock_request_handler))
119-
self.assertEqual(True, mock_do_update_groups.called, "ttl expired")
120-
mock_do_update_groups.reset_mock()
121-
config.authenticator.user_states = copy.deepcopy(saved_state)
122-
mock_time.return_value = 10000.01
123-
124-
# session expire test
125-
mock_time.return_value = 10000.01 + 601
126-
self.assertEqual(False, config.authenticator.validate_user("user@test.com", mock_request_handler), "shoud be expired")
127-
self.assertEqual(True, mock_persist_session.called, "dump state to file")
128-
mock_persist_session.reset_mock()
129-
self.assertIsNone(config.authenticator.user_states.get("user@test.com"), "removed from state")
130-
self.assertListEqual([], config.authenticator.get_groups("user@test.com"))
131-
config.authenticator.user_states = copy.deepcopy(saved_state)
132-
mock_time.return_value = 10000.01
133-
134-
# test clean expire
135-
mock_time.return_value = 10000.01 + 601
136-
config.authenticator.clean_sessions()
137-
self.assertIsNone(config.authenticator.user_states.get("user@test.com"))
138-
config.authenticator.user_states = copy.deepcopy(saved_state)
139-
mock_time.return_value = 10000.01
140-
141-
@patch('time.time', mock_time)
142-
@patch('auth.auth_gitlab.GitlabOAuthAuthenticator.do_update_user', mock_do_update_user)
143-
@patch('auth.auth_gitlab.GitlabOAuthAuthenticator.do_update_groups', mock_do_update_groups)
144-
def test_gitlab_oauth_user_read_scope(self):
145-
now = time.time()
146-
147-
state = {
148-
"user@test.com": {
149-
"groups": ["testgroup"],
150-
"updating": False,
151-
"updated": 0,
152-
"visit": now-10,
153-
"id": 1,
154-
"username": "test",
155-
"name": "John",
156-
"email": "user@test.com",
157-
"state": "active"
158-
}
159-
}
160-
161-
config = _from_json({
162-
'auth': {
163-
"type": "gitlab",
164-
"url": "https://gitlab",
165-
"client_id": "1234",
166-
"secret": "abcd",
167-
"group_search": "script-server",
168-
"auth_info_ttl": 80,
169-
"session_expire_minutes": 1,
170-
"group_support": False
171-
},
172-
'access': {
173-
'allowed_users': []
174-
}})
175-
176-
self.assertIsInstance(config.authenticator, GitlabOAuthAuthenticator)
177-
self.assertEqual("read_user", config.authenticator._client_visible_config['oauth_scope'])
178-
config.authenticator.user_states = state
179-
self.assertEqual(True, config.authenticator.validate_user("user@test.com", mock_request_handler))
180-
self.assertEqual(False, mock_do_update_groups.called, "update==0, gitlab updating but not groups")
181-
self.assertEqual(True, mock_do_update_user.called, "update==0, gitlab updating only user")
182-
mock_do_update_groups.reset_mock()
183-
mock_do_update_user.reset_mock()
184-
185-
config.authenticator.gitlab_update = None
186-
self.assertEqual(True, config.authenticator.validate_user("user@test.com", mock_request_handler))
187-
self.assertEqual(False, mock_do_update_groups.called, "gitab update disabled")
188-
self.assertEqual(False, mock_do_update_user.called, "gitab update disabled")
189-
mock_do_update_groups.reset_mock()
190-
mock_do_update_user.reset_mock()
191-
192-
def tearDown(self):
193-
test_utils.cleanup()
194-
195-
196-
def _from_json(content):
197-
json_obj = json.dumps(content)
198-
conf_path = os.path.join(test_utils.temp_folder, 'conf.json')
199-
file_utils.write_file(conf_path, json_obj)
200-
return server_conf.from_json(conf_path, test_utils.temp_folder)
9+
10+
11+
def create_config(*, url=None, group_search=None, group_support=None):
12+
config = {
13+
'client_id': '1234',
14+
'secret': 'hello world?'
15+
}
16+
17+
if url is not None:
18+
config['url'] = url
19+
if group_search is not None:
20+
config['group_search'] = group_search
21+
if group_support is not None:
22+
config['group_support'] = group_support
23+
24+
return config
25+
26+
27+
class TestAuthConfig(unittest.TestCase):
28+
def test_client_visible_config(self):
29+
authenticator = GitlabOAuthAuthenticator(create_config(url='https://my.gitlab.host'))
30+
31+
client_visible_config = authenticator._client_visible_config
32+
self.assertEqual('1234', client_visible_config['client_id'])
33+
self.assertEqual('https://my.gitlab.host/oauth/authorize', client_visible_config['oauth_url'])
34+
self.assertEqual('api', client_visible_config['oauth_scope'])
35+
36+
def test_client_visible_config_when_groups_disabled(self):
37+
authenticator = GitlabOAuthAuthenticator(create_config(group_support=False))
38+
39+
client_visible_config = authenticator._client_visible_config
40+
self.assertEqual('read_user', client_visible_config['oauth_scope'])
41+
42+
def test_client_visible_config_when_default_url(self):
43+
authenticator = GitlabOAuthAuthenticator(create_config())
44+
45+
client_visible_config = authenticator._client_visible_config
46+
self.assertEqual('https://gitlab.com/oauth/authorize', client_visible_config['oauth_url'])
47+
48+
49+
class TestFetchUserInfo(AsyncTestCase):
50+
@patch('tornado.auth.OAuth2Mixin.oauth2_request')
51+
@gen_test
52+
def test_fetch_user_info(self, mock_request):
53+
response = {'email': 'me@gmail.com', 'state': 'active'}
54+
mock_request.return_value = response
55+
56+
authenticator = GitlabOAuthAuthenticator(create_config(url='https://my.gitlab.host'))
57+
58+
user_info = yield authenticator.fetch_user_info('my_token_2')
59+
self.assertEqual(_OauthUserInfo('me@gmail.com', True, response), user_info)
60+
61+
mock_request.assert_called_with('https://my.gitlab.host/api/v4/user', 'my_token_2')
62+
63+
@patch('tornado.auth.OAuth2Mixin.oauth2_request')
64+
@gen_test
65+
def test_fetch_user_info_when_no_response(self, mock_request):
66+
mock_request.return_value = None
67+
68+
authenticator = GitlabOAuthAuthenticator(create_config())
69+
70+
user_info = yield authenticator.fetch_user_info('my_token_2')
71+
self.assertEqual(None, user_info)
72+
73+
@patch('tornado.auth.OAuth2Mixin.oauth2_request')
74+
@gen_test
75+
def test_fetch_user_info_when_not_active(self, mock_request):
76+
response = {'email': 'me@gmail.com', 'state': 'something'}
77+
mock_request.return_value = response
78+
79+
authenticator = GitlabOAuthAuthenticator(create_config())
80+
81+
user_info = yield authenticator.fetch_user_info('my_token_2')
82+
self.assertEqual(_OauthUserInfo('me@gmail.com', False, response), user_info)
83+
84+
85+
class TestFetchUserGroups(AsyncTestCase):
86+
@patch('tornado.auth.OAuth2Mixin.oauth2_request')
87+
@gen_test
88+
def test_fetch_user_info(self, mock_request):
89+
response = [{'full_path': 'group1'}, {'full_path': 'group2'}, {'something': 'group3'}]
90+
mock_request.return_value = response
91+
92+
authenticator = GitlabOAuthAuthenticator(create_config(url='https://my.gitlab.host'))
93+
94+
groups = yield authenticator.fetch_user_groups('my_token_2')
95+
self.assertEqual(['group1', 'group2'], groups)
96+
97+
mock_request.assert_called_with('https://my.gitlab.host/api/v4/groups',
98+
access_token='my_token_2',
99+
all_available='false',
100+
per_page=100)
101+
102+
@patch('tornado.auth.OAuth2Mixin.oauth2_request')
103+
@gen_test
104+
def test_fetch_user_info_when_search(self, mock_request):
105+
authenticator = GitlabOAuthAuthenticator(create_config(url='https://my.gitlab.host', group_search='abc'))
106+
107+
yield authenticator.fetch_user_groups('my_token_2')
108+
109+
mock_request.assert_called_with('https://my.gitlab.host/api/v4/groups',
110+
access_token='my_token_2',
111+
all_available='false',
112+
per_page=100,
113+
search='abc')

0 commit comments

Comments
 (0)