Skip to content

Commit f8d54d8

Browse files
committed
raise authorization error on HTTP 403
1 parent f7b5144 commit f8d54d8

File tree

5 files changed

+67
-7
lines changed

5 files changed

+67
-7
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@ Unreleased
33
----------
44
-
55

6+
v1.4 (2019-10-15)
7+
-----------------
8+
**Changes**
9+
- `PyMAS.score_code` now supports a `dest='Python'` option to retrieve the generated Python wrapper code.
10+
- `register_model` task includes a `python_wrapper.py` file when registering a Python model.
11+
- Improved error message when user lacks required permissions to register a model.
12+
13+
**Bugfixes**
14+
- Fixed an issue with CAS/EP score code that caused problems with model performance metrics.
15+
16+
617
v1.3 (2019-10-10)
718
-----------------
819
**Improvements**

src/sasctl/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Copyright © 2019, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
55
# SPDX-License-Identifier: Apache-2.0
66

7-
__version__ = '1.3'
7+
__version__ = '1.4'
88
__author__ = 'SAS'
99
__credits__ = ['Yi Jian Ching, Lucas De Paula, James Kochuba, Peter Tobac, '
1010
'Chris Toth, Jon Walker']

src/sasctl/exceptions.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,10 @@ def __init__(self, username, *args, **kwargs):
1313
super(AuthenticationError, self).__init__(msg, *args, **kwargs)
1414

1515

16+
class AuthorizationError(RuntimeError):
17+
"""A user lacks permission to perform an action."""
18+
pass
19+
20+
1621
class JobTimeoutError(RuntimeError):
1722
pass

src/sasctl/tasks.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515
import sys
1616
import warnings
1717

18+
from six.moves.urllib.error import HTTPError
19+
1820
from . import utils
1921
from .core import RestObj, current_session, get, get_link, request_link
22+
from .exceptions import AuthorizationError
2023
from .services import model_management as mm
2124
from .services import model_publish as mp
2225
from .services import model_repository as mr
@@ -180,10 +183,20 @@ def get_version(x):
180183
raise ValueError("Project '{}' not found".format(project))
181184

182185
# Use default repository if not specified
183-
if repository is None:
184-
repo_obj = mr.default_repository()
185-
else:
186-
repo_obj = mr.get_repository(repository)
186+
try:
187+
if repository is None:
188+
repo_obj = mr.default_repository()
189+
else:
190+
repo_obj = mr.get_repository(repository)
191+
except HTTPError as e:
192+
if e.code == 403:
193+
raise AuthorizationError('Unable to register model. User account '
194+
'does not have read permissions for the '
195+
'/modelRepository/repositories/ URL. '
196+
'Please contact your SAS Viya '
197+
'administrator.')
198+
else:
199+
raise e
187200

188201
# Unable to find or create the repo.
189202
if repo_obj is None and repository is None:

tests/unit/test_tasks.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from six.moves import mock
99

1010
from sasctl.core import RestObj
11-
11+
from sasctl._services.model_repository import ModelRepository
1212

1313
def test_sklearn_metadata():
1414
pytest.importorskip('sklearn')
@@ -77,7 +77,7 @@ def test_parse_module_url():
7777
def test_save_performance_project_types():
7878
from sasctl.tasks import update_model_performance
7979

80-
with mock.patch('sasctl._services.model_repository.ModelRepository''.get_model') as model:
80+
with mock.patch('sasctl._services.model_repository.ModelRepository.get_model') as model:
8181
with mock.patch('sasctl._services.model_repository.ModelRepository.get_project') as project:
8282
model.return_value = RestObj(name='fakemodel', projectId=1)
8383

@@ -98,3 +98,34 @@ def test_save_performance_project_types():
9898
update_model_performance(None, None, None)
9999

100100
# Check projects w/ invalid properties
101+
102+
103+
@mock.patch.object(ModelRepository, 'get_repository')
104+
@mock.patch.object(ModelRepository, 'get_project')
105+
def test_register_model_403_error(get_project, get_repository):
106+
"""Verify HTTP 403 is converted to a user-friendly error.
107+
108+
Depending on environment configuration, this can happen when attempting to
109+
find a repository.
110+
111+
See: https://github.com/sassoftware/python-sasctl/issues/39
112+
"""
113+
114+
from six.moves.urllib.error import HTTPError
115+
from sasctl.exceptions import AuthorizationError
116+
from sasctl.tasks import register_model
117+
118+
get_project.return_value = {'name': 'Project Name'}
119+
get_repository.side_effect = HTTPError(None, 403, None, None, None)
120+
121+
# HTTP 403 error when getting repository should throw a user-friendly
122+
# AuthorizationError
123+
with pytest.raises(AuthorizationError):
124+
register_model(None, 'model name', 'project name')
125+
126+
# All other errors should be bubbled up
127+
get_repository.side_effect = HTTPError(None, 404, None, None, None)
128+
with pytest.raises(HTTPError):
129+
register_model(None, 'model name', 'project name')
130+
131+

0 commit comments

Comments
 (0)