Skip to content
This repository has been archived by the owner on Nov 10, 2021. It is now read-only.

Commit

Permalink
Merge pull request #1 from jeffFranklin/master
Browse files Browse the repository at this point in the history
IRWS publishing preference post (EDS-110)
  • Loading branch information
jeffFranklin committed May 21, 2015
2 parents 74b8539 + e2011a4 commit e0292c0
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 9 deletions.
3 changes: 3 additions & 0 deletions restclients/dao.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ def getURL(self, url, headers):
def putURL(self, url, headers, body):
return self._putURL('irws', url, headers, body)

def postURL(self, url, headers, body):
return self._postURL('irws', url, headers, body)

def _getDAO(self):
return self._getModule('RESTCLIENTS_IRWS_DAO_CLASS', IRWSFile)

Expand Down
40 changes: 35 additions & 5 deletions restclients/dao_implementation/irws.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from restclients.mock_http import MockHTTP
import re
import logging
import json
from restclients.dao_implementation.live import get_con_pool, get_live_url
from restclients.dao_implementation.mock import get_mockdata_url

Expand All @@ -23,19 +24,42 @@ class File(object):
RESTCLIENTS_IRWS_DAO_CLASS = 'restclients.dao_implementation.irws.File'
"""
# cache of results to fake puts and posts in memory
_cache = {}

def getURL(self, url, headers):
return get_mockdata_url("irws", "file", url, headers)
if url in File._cache:
response = MockHTTP()
response.status = 200
response.data = File._cache[url]
response.headers = {'Content-Type': 'application/json'}
else:
response = get_mockdata_url("irws", "file", url, headers)
File._cache[url] = response.data
return response

def putURL(self, url, headers, body):
response = MockHTTP()
logger.debug('made it to putURL')

response.status = 200
response.headers = {"X-Data-Source": "GWS file mock data",
"Content-Type": 'application/json'}
response.data = body
response.headers = {"Content-Type": 'application/json'}
if url in File._cache:
cache = json.loads(File._cache[url])
request = json.loads(body)
type = request.keys()[0]
for attr in request[type][0].keys():
cache[type][0][attr] = request[type][0][attr]
File._cache[url] = json.dumps(cache)
response.data = File._cache[url]
response.status = 200
else:
response.data = body
response.status = 404
return response

def postURL(self, url, headers, body):
return self.putURL(url, headers, body)


class AlwaysJAverage(object):
"""
Expand Down Expand Up @@ -91,6 +115,12 @@ def putURL(self, url, headers, body):
url, headers=headers, body=body,
service_name='irws')

def postURL(self, url, headers, body):
return get_live_url(self.pool, 'POST',
settings.RESTCLIENTS_IRWS_HOST,
url, headers=headers, body=body,
service_name='irws')

_pool = None
@property
def pool(self):
Expand Down
8 changes: 8 additions & 0 deletions restclients/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ class InvalidIRWSName(Exception):
"""Exception for invalid IRWS name."""
pass

class InvalidIRWSPerson(Exception):
"""Exception for invalid IRWS name."""
pass

class IRWSPersonNotFound(Exception):
"""Exception for netids that don't exist"""
pass

class DataFailureException(Exception):
"""
This exception means there was an error fetching content
Expand Down
58 changes: 55 additions & 3 deletions restclients/irws.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from restclients.exceptions import InvalidRegID, InvalidNetID, InvalidEmployeeID
from restclients.exceptions import InvalidIdCardPhotoSize
from restclients.exceptions import DataFailureException
from restclients.exceptions import InvalidIRWSName
from restclients.exceptions import InvalidIRWSName, InvalidIRWSPerson, IRWSPersonNotFound
from restclients.models.irws import Name, HeppsPerson, PersonIdentity
from StringIO import StringIO
from urllib import urlencode
Expand Down Expand Up @@ -92,14 +92,46 @@ def get_hepps_person_by_uri(self, uri):
If the record id isn't found, nothing will be returned. If there is an error
communicating with the IRWS, a DataFailureException will be thrown.
"""
url = "/%s/v1/%s" % (self._service_name, uri)
url = "/%s/v1%s" % (self._service_name, uri)
response = IRWS_DAO().getURL(url, {"Accept": "application/json"})

if response.status != 200:
raise DataFailureException(url, response.status, response.data)

return self._hepps_person_from_json(response.data)

def get_hepps_person_by_netid(self, netid):
"""
Returns a restclients.irws.HeppsPerson object for a given netid. Two round
trips - one to get the identity, and a second to look up a person based on
the 'hepps' uri in the payload
"""
identity = self.get_identity_by_netid(netid)
if 'hepps' not in identity.identifiers.keys():
raise IRWSPersonNotFound('netid ' + netid + ' not a hepps person')
return self.get_hepps_person_by_uri(identity.identifiers['hepps'])

def post_hepps_person_by_netid(self, netid, data):
"""
Post to the irws person hepps resource.
We look up the person by netid to get the uri to post to.
"""
if not self.valid_uwnetid(netid):
raise InvalidNetID(netid)
hepps_person = self.valid_hepps_person_from_json(data)
identity = self.get_identity_by_netid(netid)
if 'hepps' not in identity.identifiers.keys():
raise IRWSPersonNotFound('netid ' + netid + ' not a hepps person')
post_url = '/{}/v1{}'.format(self._service_name,
identity.identifiers['hepps'])
response = IRWS_DAO().postURL(post_url,
{'Accept': 'application/json'},
json.dumps(hepps_person))
if response.status != 200:
raise DataFailureException(post_url, response.status, response.data)

return response.status

def valid_uwnetid(self, netid):
uwnetid = str(netid)
return (self._re_personal_netid.match(uwnetid) != None
Expand Down Expand Up @@ -137,6 +169,26 @@ def valid_irws_name_from_json(self, data):

return pd

def valid_hepps_person_from_json(self, data):
"""
Validate input of supported fields and return an
object that can be posted to irws
"""
post_person = {}
try:
data_person = json.loads(data)
post_person['wp_publish'] = data_person.pop('wp_publish')
if len(data_person.keys()) != 0:
logger.info('ignoring the following keys for post: {}'.format(
', '.join(data_person.keys())))
except:
raise InvalidIRWSPerson('invalid json')

if post_person['wp_publish'] not in ('Y', 'N', 'E'):
raise InvalidIRWSPerson('wp_publish can only be Y, N, or E')

return {'person': [post_person]}

def valid_name_part(self, name):
return (len(name) <= 64 and
self._re_name_part.match(name) != None)
Expand All @@ -158,7 +210,7 @@ def _hepps_person_from_json(self, data):
person.category_name = person_data['category_name']

if 'wp_publish' in person_data: person.wp_publish = person_data['wp_publish']
else: person.wp_publish = 'Y'
else: person.wp_publish = 'N' # default to no
return person

def _name_from_json(self, data):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"person": [
{
"validid": "000210870",
"regid": "28098ACBAC71425D9B2912757E4EF3AE",
"lname": "Harrison",
"fname": "Dolley",
"pac": "E",
"category_code": "4",
"category_name": "Staff",
"college": "99",
"department": ".TEST ",
"unit": "000",
"hepps_type": "E",
"hepps_status": "A",
"budget": "000001",
"source_code": "1",
"source_name": "UW Faculty/Staff",
"status_code": "1",
"status_name": "Current",
"in_feed": "2",
"logname": "registry2:getvalidations:NewID/69.91.223.171:anonymous@netid11.cac.washington.edu",
"created": "2015-05-14 16:01:58.671418",
"updated": "2015-05-14 16:52:52.452015"
}
],
"totalcount": 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"person": [
{
"identity": {
"regid": "F533DB1751A34FF1878CA1C88A3D179C",
"lname": "Adams",
"fname": "Dwight",
"identifiers": {
"sdb": "/person/sdb/990100554"
}
}
}
],
"totalcount": 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"person": [
{
"identity": {
"regid": "28098ACBAC71425D9B2912757E4EF3AE",
"lname": "Harrison",
"fname": "Dolley",
"identifiers": {
"hepps": "/person/hepps/000210870"
}
}
}
],
"totalcount": 1
}
101 changes: 100 additions & 1 deletion restclients/test/irws.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,45 @@
from django.test import TestCase, override_settings
from django.conf import settings
from restclients.irws import IRWS
from restclients.exceptions import InvalidIRWSName
from restclients.exceptions import InvalidIRWSName, DataFailureException, InvalidNetID
from restclients.exceptions import IRWSPersonNotFound, InvalidIRWSPerson
from restclients.dao_implementation.irws import File

logger = logging.getLogger(__name__)


@override_settings(RESTCLIENTS_IRWS_DAO_CLASS='restclients.dao_implementation.irws.File',
RESTCLIENTS_IRWS_SERVICE_NAME='registry-dev')
class IRWSTest(TestCase):
def setUp(self):
File._cache = {}

def test_get_name_by_netid(self):
irws = IRWS()
name = irws.get_name_by_netid('javerage')
self.assertEquals(name.display_cname, 'JAMES AVERAGE STUDENT')

def test_put_name_by_netid(self):
irws = IRWS()
# prime the cache first
irws.get_name_by_netid('javerage')

response = irws.put_name_by_netid(
'javerage',
self._json_name_from_tuple(('J', '', 'Student')))
self.assertEquals(200, response)
name = irws.get_name_by_netid('javerage')
self.assertEquals('J', name.display_fname)
self.assertEquals('', name.display_mname)
self.assertEquals('Student', name.display_lname)

def test_put_name_by_netid_no_user(self):
irws = IRWS()
self.assertRaises(DataFailureException,
irws.put_name_by_netid,
'nonuser',
self._json_name_from_tuple(('J', '', 'Student')))

def test_valid_name_part_good(self):
irws = IRWS()
self.assertTrue(irws.valid_name_part('james'))
Expand Down Expand Up @@ -119,6 +144,80 @@ def test_valid_irws_name_too_long(self):
irws.valid_irws_name_from_json,
bad_name)

def test_get_identity_by_netid(self):
irws = IRWS()
identity = irws.get_identity_by_netid('javerage')
self.assertNotEqual(0, len(identity.identifiers.keys()))

def test_get_identity_by_netid_bad_netid(self):
irws = IRWS()
self.assertRaises(InvalidNetID,
irws.get_identity_by_netid,
'lkfajdslkjf#@$$@')

def test_get_identity_by_netid_nonexistent(self):
irws = IRWS()
self.assertRaises(DataFailureException,
irws.get_identity_by_netid,
'nonuser')

def test_get_hepps_person_by_netid(self):
irws = IRWS()
# idtest56 is set up to be a hepps person
hepps_person = irws.get_hepps_person_by_netid('idtest56')
self.assertEqual('N', hepps_person.wp_publish)
self.assertEqual('28098ACBAC71425D9B2912757E4EF3AE', hepps_person.regid)

def test_get_hepps_person_by_netid_not_hepps(self):
irws = IRWS()
# idtest55 is set up to NOT be a hepps person
self.assertRaises(IRWSPersonNotFound,
irws.get_hepps_person_by_netid,
'idtest55')

def test_post_hepps_person_by_netid(self):
irws = IRWS()
netid = 'idtest56'
# prime the cache
irws.get_hepps_person_by_netid(netid)
response = irws.post_hepps_person_by_netid(
netid,
'{"wp_publish": "E"}')
self.assertEqual(200, response)
identity = irws.get_hepps_person_by_netid(netid)
self.assertEqual('E', identity.wp_publish)

def test_post_hepps_person_by_netid_not_hepps(self):
irws = IRWS()
self.assertRaises(IRWSPersonNotFound,
irws.post_hepps_person_by_netid,
'idtest55',
'{"wp_publish": "E"}')

def test_post_hepps_person_by_netid_data_failure(self):
self.assertRaises(DataFailureException,
IRWS().post_hepps_person_by_netid,
'idtest56',
'{"wp_publish": "E"}')

def test_valid_hepps_person_from_json(self):
person = IRWS().valid_hepps_person_from_json('{"wp_publish": "Y"}')
expected = json.dumps({'person': [{'wp_publish': 'Y'}]})
self.assertEqual(expected, json.dumps(person))
# test all the possible values
person = IRWS().valid_hepps_person_from_json('{"wp_publish": "N"}')
person = IRWS().valid_hepps_person_from_json('{"wp_publish": "E"}')

def test_valid_hepps_person_from_json_bad_payload(self):
self.assertRaises(InvalidIRWSPerson,
IRWS().valid_hepps_person_from_json,
'{"wp_publish": "J"}')

def test_valid_hepps_person_from_json_bad_json(self):
self.assertRaises(InvalidIRWSPerson,
IRWS().valid_hepps_person_from_json,
'{"wp_publish":')

def _json_name_from_tuple(self, x):
return json.dumps({'display_fname': x[0],
'display_mname': x[1],
Expand Down

0 comments on commit e0292c0

Please sign in to comment.