Exemplo n.º 1
0
    def test_setup_job(self):
        '''
        Upload and supply a data file for some jobs, then verify the form comes back.
        '''
        username, password = self.getUsernamePassword()
        user_uri = self._create_user(username, password)
        client = NMTKClient(self.site_url)
        response = client.login(username=username, password=password)
        filename = self.get_support_file('test1.geojson')
        test_file = client.uploadData(filename,
                                      description='Test data file (MSP)')
        logger.debug('URI of test file is %s', test_file)

        tool_url = client.getURL('api', 'tool/')
        job_url = client.getURL('api', 'job/')
        response = client.get(tool_url, params={'format': 'json'})
        tools = response.json()['objects']
        tool_uri_list = []
        # Get a list of all the Tool Resource URIs for Minnesota models,
        # since the test1.geojson file is a MN model-specific data file.
        for tool in tools:
            if 'minnesota' in tool['name'].lower():
                tool_uri_list.append(tool['resource_uri'])
        job_uri_list = []
        for uri in tool_uri_list:
            data = {
                'tool': client.neuter_url(uri),
                'data_file': client.neuter_url(test_file)
            }
            response = client.post(job_url,
                                   data=json.dumps(data),
                                   headers={
                                       'Content-Type': 'application/json',
                                   })
            self.assertEqual(
                response.status_code, 201,
                ('Expected job to be created - ' + 'got back %s instead') %
                (response.status_code))
            logger.debug('Created new job entry with URI %s',
                         response.headers['location'])
            job_uri_list.append(response.headers['location'])
        for uri in job_uri_list:
            response = client.get(uri, params={'format': 'json'})
            data = response.json()
            self.assertTrue(
                len(json.dumps(data.get('form', ''))) > 10,
                'Expected the form to appear in' + 'the output JSON (got %s)' %
                (response.text, ))
Exemplo n.º 2
0
    def test_submit_job_other_user_denied_access(self):
        '''
        Verify that once a job is submitted/created, other users cannot access.
        '''
        username, password = self.getUsernamePassword()
        user_uri = self._create_user(username, password)
        client = NMTKClient(self.site_url)
        response = client.login(username=username, password=password)
        username2, password2 = self.getUsernamePassword()
        user_uri2 = self._create_user(username2, password2)
        client2 = NMTKClient(self.site_url)
        client2.login(username=username2, password=password2)
        filename = self.get_support_file('test1.geojson')
        test_file = client.uploadData(filename,
                                      description='Test data file (MSP)')
        logger.debug('URI of test file is %s', test_file)

        tool_url = client.getURL('api', 'tool/')
        job_url = client.getURL('api', 'job/')
        response = client.get(tool_url, params={'format': 'json'})
        tools = response.json()['objects']
        # Get a list of all the Tool Resource URIs for Minnesota models,
        # since the test1.geojson file is a MN model-specific data file.
        for tool in tools:
            if 'umn' in tool['name'].lower():
                tool_uri = tool['resource_uri']
                break
        data = {
            'tool': client.neuter_url(tool_uri),
            'description': 'how now brown cow'
        }

        response = client.post(job_url,
                               data=json.dumps(data),
                               headers={
                                   'Content-Type': 'application/json',
                               })
        self.assertEqual(
            response.status_code, 201,
            ('Expected job to be created - ' + 'got back %s instead') %
            (response.status_code, ))
        job_uri = response.headers['location']
        # Now we have a job, let's get the form, generate the response, and
        # submit it back to the user.
        response = client2.get(job_uri, params={'format': 'json'})
        self.assertEqual(
            response.status_code, 401,
            'Expected client2 to get a 401, not %s' % (response.status_code, ))
Exemplo n.º 3
0
    def test_prevent_user_from_using_other_user_data(self):
        '''
        Verify that one user can neither access, nor submit jobs, with another users data
        '''
        username, password = self.getUsernamePassword()
        user_uri = self._create_user(username, password)
        username2, password2 = self.getUsernamePassword()
        user_uri = self._create_user(username2, password2)
        client = NMTKClient(self.site_url)
        client.login(username=username, password=password)
        client2 = NMTKClient(self.site_url)
        client2.login(username=username2, password=password2)
        filename = self.get_support_file('test1.geojson')
        test_file = client.uploadData(filename,
                                      description='Test configuration file')
        # Just try to access the other users file
        response = client2.get(test_file, params={'format': 'json'})
        logger.debug('Response when getting other users file was %s',
                     response.status_code)
        self.assertEqual(response.status_code, 401,
                         'Expected a 401, got a %s' % (response.status_code, ))
        # Try to create a job with the other users file
        job_url = client.getURL('api', 'job/')
        tool_url = client.getURL('api', 'tool/')

        response = client.get(tool_url, params={'format': 'json'})
        tools = response.json()['objects']
        # Get a list of all the Tool Resource URIs for Minnesota models,
        # since the test1.geojson file is a MN model-specific data file.
        for tool in tools:
            if 'umn' in tool['name'].lower():
                tool_uri = tool['resource_uri']
                break
        data = {
            'tool': client.neuter_url(tool_uri),
            'description': 'how now brown cow'
        }
        logger.debug(
            'Verifying that user A cannot create a job with User B data')
        response = client2.post(job_url,
                                data=json.dumps(data),
                                headers={
                                    'Content-Type': 'application/json',
                                })
        logger.debug('Status code was %s', response.status_code)
        logger.debug('Response text was %s', response.text)
Exemplo n.º 4
0
 def test_submit_job_other_user_denied_access(self):
     '''
     Verify that once a job is submitted/created, other users cannot access.
     '''
     username, password=self.getUsernamePassword()
     user_uri=self._create_user(username,password)
     client=NMTKClient(self.site_url)
     response=client.login(username=username,
                           password=password)
     username2, password2=self.getUsernamePassword()
     user_uri2=self._create_user(username2,password2)
     client2=NMTKClient(self.site_url)
     client2.login(username=username2,
                   password=password2)
     filename=self.get_support_file('test1.geojson')
     test_file=client.uploadData(filename, 
                                 description='Test data file (MSP)')
     logger.debug('URI of test file is %s', test_file)
     
     tool_url=client.getURL('api','tool/')
     job_url=client.getURL('api','job/')
     response=client.get(tool_url, params={'format': 'json'})
     tools=response.json()['objects']
     # Get a list of all the Tool Resource URIs for Minnesota models,
     # since the test1.geojson file is a MN model-specific data file.
     for tool in tools:
         if 'umn' in tool['name'].lower():
             tool_uri=tool['resource_uri']
             break
     data={'tool': client.neuter_url(tool_uri),
           'description': 'how now brown cow'}
     
     response=client.post(job_url, 
                          data=json.dumps(data),
                          headers={'Content-Type': 'application/json',})
     self.assertEqual(response.status_code, 201,
                      ('Expected job to be created - ' +
                       'got back %s instead') % (response.status_code,))
     job_uri=response.headers['location']
     # Now we have a job, let's get the form, generate the response, and
     # submit it back to the user.
     response=client2.get(job_uri, params={'format': 'json'})
     self.assertEqual(response.status_code, 401,
                      'Expected client2 to get a 401, not %s' % 
                      (response.status_code,))
     
Exemplo n.º 5
0
 def test_setup_job(self):
     '''
     Upload and supply a data file for some jobs, then verify the form comes back.
     '''
     username, password=self.getUsernamePassword()
     user_uri=self._create_user(username,password)
     client=NMTKClient(self.site_url)
     response=client.login(username=username,
                           password=password)
     filename=self.get_support_file('test1.geojson')
     test_file=client.uploadData(filename, 
                                 description='Test data file (MSP)')
     logger.debug('URI of test file is %s', test_file)
     
     tool_url=client.getURL('api','tool/')
     job_url=client.getURL('api','job/')
     response=client.get(tool_url, params={'format': 'json'})
     tools=response.json()['objects']
     tool_uri_list=[]
     # Get a list of all the Tool Resource URIs for Minnesota models,
     # since the test1.geojson file is a MN model-specific data file.
     for tool in tools:
         if 'minnesota' in tool['name'].lower():
             tool_uri_list.append(tool['resource_uri'])
     job_uri_list=[]
     for uri in tool_uri_list:
         data={'tool': client.neuter_url(uri),
               'data_file': client.neuter_url(test_file)}
         response=client.post(job_url, 
                              data=json.dumps(data),
                              headers={'Content-Type': 'application/json',})
         self.assertEqual(response.status_code, 201,
                          ('Expected job to be created - ' +
                           'got back %s instead') % (
                          response.status_code))
         logger.debug('Created new job entry with URI %s', 
                      response.headers['location'])
         job_uri_list.append(response.headers['location'])
     for uri in job_uri_list:
         response=client.get(uri, params={'format': 'json'})
         data=response.json()
         self.assertTrue(len(json.dumps(data.get('form',''))) > 10, 
                         'Expected the form to appear in' +
                         'the output JSON (got %s)' % (response.text,))
Exemplo n.º 6
0
    def test_prevent_user_from_using_other_user_data(self):
        '''
        Verify that one user can neither access, nor submit jobs, with another users data
        '''
        username, password=self.getUsernamePassword()
        user_uri=self._create_user(username,password)
        username2, password2=self.getUsernamePassword()
        user_uri=self._create_user(username2,password2)
        client=NMTKClient(self.site_url)
        client.login(username=username,
                     password=password)
        client2=NMTKClient(self.site_url)
        client2.login(username=username2,
                      password=password2)
        filename=self.get_support_file('test1.geojson')
        test_file=client.uploadData(filename, 
                                    description='Test configuration file')
        # Just try to access the other users file
        response=client2.get(test_file, params={'format': 'json'})
        logger.debug('Response when getting other users file was %s',
                     response.status_code)
        self.assertEqual(response.status_code, 401,
                         'Expected a 401, got a %s' % (response.status_code,))
        # Try to create a job with the other users file
        job_url=client.getURL('api','job/')
        tool_url=client.getURL('api','tool/')

        response=client.get(tool_url, params={'format': 'json'})
        tools=response.json()['objects']
        # Get a list of all the Tool Resource URIs for Minnesota models,
        # since the test1.geojson file is a MN model-specific data file.
        for tool in tools:
            if 'umn' in tool['name'].lower():
                tool_uri=tool['resource_uri']
                break
        data={'tool': client.neuter_url(tool_uri),
              'description': 'how now brown cow'}
        logger.debug('Verifying that user A cannot create a job with User B data')
        response=client2.post(job_url, 
                              data=json.dumps(data),
                              headers={'Content-Type': 'application/json',})
        logger.debug('Status code was %s', response.status_code)
        logger.debug('Response text was %s', response.text)
Exemplo n.º 7
0
    def test_logout_verify(self):
        '''
        Verify that we can log out successfully.
        Verifies that logout functionality works, and that the server
        properly invalidates the session when logout is requested.  Verify
        that the correct redirect URL is provided for login after a user has
        logged out.
        '''

        client = NMTKClient(self.site_url)
        test_url = '%s%s' % (client.getURL('api'), 'job/')
        result = client.login(self.username, self.password)
        self.assertEqual(result.status_code, 302)
        result = client.get(test_url, params={'format': 'json'})
        self.assertEqual(result.status_code, 200)
        result = client.logout()
        self.assertEqual(result.status_code, 302)
        login_url = client.getURL('login')[:-1]

        result = client.get(test_url, params={'format': 'json'})
        self.assertEqual(result.status_code, 401)
Exemplo n.º 8
0
    def test_logout_verify(self):
        '''
        Verify that we can log out successfully.
        Verifies that logout functionality works, and that the server
        properly invalidates the session when logout is requested.  Verify
        that the correct redirect URL is provided for login after a user has
        logged out.
        '''

        client = NMTKClient(self.site_url)
        test_url = '%s%s' % (client.getURL('api'),
                             'job/')
        result = client.login(self.username, self.password)
        self.assertEqual(result.status_code, 302)
        result = client.get(test_url, params={'format': 'json'})
        self.assertEqual(result.status_code, 200)
        result = client.logout()
        self.assertEqual(result.status_code, 302)
        login_url = client.getURL('login')[:-1]

        result = client.get(test_url, params={'format': 'json'})
        self.assertEqual(result.status_code, 401)
Exemplo n.º 9
0
 def test_list_tools(self):
     '''
     Verify that any user (even without login) can retrieve a list of tools.
     '''
     username, password = self.getUsernamePassword()
     user_uri = self._create_user(username, password)
     client = NMTKClient(self.site_url)
     tool_url = client.getURL('api', 'tool/')
     logger.debug('Attempting to get tool list (%s) as not-logged-in user',
                  tool_url)
     response = client.get(tool_url, params={'format': 'json'})
     self.assertEqual(200, response.status_code,
                      'expected 200, not %s' % (response.status_code,))
     response = client.login(username=username,
                             password=password)
     response = client.get(tool_url, params={'format': 'json'})
     self.assertEqual(200, response.status_code,
                      'expected 200 (when logged in), not %s' %
                      (response.status_code,))
     jsdata = response.json()
     self.assertEqual(min(jsdata['meta']['total_count'],
                          jsdata['meta']['limit']), len(jsdata['objects']),
                      'Expected the number of objects returned to match the purported count!')
Exemplo n.º 10
0
 def test_list_tools(self):
     '''
     Verify that any user (even without login) can retrieve a list of tools.
     '''
     username, password = self.getUsernamePassword()
     user_uri = self._create_user(username, password)
     client = NMTKClient(self.site_url)
     tool_url = client.getURL('api', 'tool/')
     logger.debug('Attempting to get tool list (%s) as not-logged-in user',
                  tool_url)
     response = client.get(tool_url, params={'format': 'json'})
     self.assertEqual(200, response.status_code,
                      'expected 200, not %s' % (response.status_code, ))
     response = client.login(username=username, password=password)
     response = client.get(tool_url, params={'format': 'json'})
     self.assertEqual(
         200, response.status_code,
         'expected 200 (when logged in), not %s' % (response.status_code, ))
     jsdata = response.json()
     self.assertEqual(
         min(jsdata['meta']['total_count'], jsdata['meta']['limit']),
         len(jsdata['objects']),
         'Expected the number of objects returned to match the purported count!'
     )
Exemplo n.º 11
0
    def test_submit_job(self):
        '''
        Verify that we can properly submit a job (form) via the API and \
get back the (eventual) results and status of the running job.  Also ensure other \
users cannot download results.
        '''
        username, password = self.getUsernamePassword()
        user_uri = self._create_user(username, password)
        client = NMTKClient(self.site_url)
        response = client.login(username=username, password=password)
        filename = self.get_support_file('test1.geojson')
        test_file = client.uploadData(filename,
                                      description='Test data file (MSP)')
        logger.debug('URI of test file is %s', test_file)

        tool_url = client.getURL('api', 'tool/')
        job_url = client.getURL('api', 'job/')
        response = client.get(tool_url, params={'format': 'json'})
        tools = response.json()['objects']

        # Get a list of all the Tool Resource URIs for Minnesota models,
        # since the test1.geojson file is a MN model-specific data file.
        for tool in tools:
            if 'umn' in tool['name'].lower():
                tool_uri = tool['resource_uri']
                break
        data = {
            'tool': client.neuter_url(tool_uri),
            'description': 'Test job for testing by the automated test!'
        }

        response = client.post(job_url,
                               data=json.dumps(data),
                               headers={
                                   'Content-Type': 'application/json',
                               })
        #logger.debug('Result from post was %s', response.text)
        self.assertEqual(
            response.status_code, 201,
            ('Expected job to be created - ' + 'got back %s instead') %
            (response.status_code, ))
        job_uri = response.headers['location']

        # Now we have a job, let's get the form, generate the response, and
        # submit it back to the user.
        payload = {
            "config": {
                "coefficients": {
                    "Arterial_coeff": {
                        "type": "number",
                        "value": 391.8
                    },
                    "BusRoute_coeff": {
                        "type": "number",
                        "value": 100.3
                    },
                    "CBDdist_km_coeff": {
                        "type": "number",
                        "value": -40.3
                    },
                    "Collector_coeff": {
                        "type": "number",
                        "value": 611.1
                    },
                    "Crime_coeff": {
                        "type": "number",
                        "value": 2.9
                    },
                    "EmployAccess_coeff": {
                        "type": "number",
                        "value": 0
                    },
                    "LUMix_coeff": {
                        "type": "number",
                        "value": -919.9
                    },
                    "MedHHInc_coeff": {
                        "type": "number",
                        "value": 2.1
                    },
                    "OffstreetTrail_coeff": {
                        "type": "number",
                        "value": 253.8
                    },
                    "PDperkm2_coeff": {
                        "type": "number",
                        "value": -0.035
                    },
                    "PctU5_O65_coeff": {
                        "type": "number",
                        "value": 32.5
                    },
                    "Pctnonwhite_coeff": {
                        "type": "number",
                        "value": -29.8
                    },
                    "Pctw4ormore_coeff": {
                        "type": "number",
                        "value": 371.4
                    },
                    "Precip_coeff": {
                        "type": "number",
                        "value": -127.8
                    },
                    "Principal_coeff": {
                        "type": "number",
                        "value": 66.4
                    },
                    "Tmax_coeff": {
                        "type": "number",
                        "value": -26
                    },
                    "WatDist_km_coeff": {
                        "type": "number",
                        "value": -21.6
                    },
                    "Year_coeff": {
                        "type": "number",
                        "value": -5.9
                    },
                    "constant": {
                        "type": "number",
                        "value": 788.6
                    }
                },
                "data": {
                    "Arterial": {
                        "type": "property",
                        "value": "Arterial"
                    },
                    "BusRoute": {
                        "type": "property",
                        "value": "BusRoute"
                    },
                    "CBDdist_km": {
                        "type": "property",
                        "value": "CBDdist_km"
                    },
                    "Collector": {
                        "type": "property",
                        "value": "Collector"
                    },
                    "Crime": {
                        "type": "property",
                        "value": "Crime"
                    },
                    "EmployAccess": {
                        "type": "property",
                        "value": "EmployAccess"
                    },
                    "LUMix": {
                        "type": "property",
                        "value": "LUMix"
                    },
                    "MedHHInc": {
                        "type": "property",
                        "value": "MedHHInc"
                    },
                    "OffstreetTrail": {
                        "type": "property",
                        "value": "OffstreetTrail"
                    },
                    "PDperkm2": {
                        "type": "property",
                        "value": "PDperkm2"
                    },
                    "PctU5_O65": {
                        "type": "property",
                        "value": "PctU5_O65"
                    },
                    "Pctnonwhite": {
                        "type": "property",
                        "value": "Pctnonwhite"
                    },
                    "Pctw4ormore": {
                        "type": "property",
                        "value": "Pctw4ormore"
                    },
                    "Principal": {
                        "type": "property",
                        "value": "Principal"
                    },
                    "WatDist_km": {
                        "type": "property",
                        "value": "WatDist_km"
                    }
                },
                "results": {
                    "result": {
                        "type": "string",
                        "value": "ped12ols"
                    }
                }
            },
            "file_config": {
                "data": test_file
            }
        }
        data = client.get(job_uri, params={'format': 'json'}).json()
        data.update(payload)
        job_id = data['id']

        response = client.put(job_uri,
                              headers={
                                  'Content-Type': 'application/json',
                              },
                              data=json.dumps(data))
        logger.debug('Response from job update was %s', response.text)
        self.assertTrue(
            response.status_code in (204, 202),
            'Expected a return code of 204/202 with valid ' +
            'data provided got (%s)' % (response.status_code))

        # Now check the status to wait for completion
        timeout = time.time() + 120
        status_url = client.getURL('api', 'job_status/')
        params = {'job': job_id, 'format': 'json', 'limit': 1}
        steps = ['Parameter & data file validation complete.', 'COMPLETE']
        prev_response = ''
        while time.time() < timeout:
            response = client.get(status_url, params=params)
            self.assertEqual(response.status_code, 200,
                             'Expected to get valid response back')
            if len(response.text):
                json_data = response.json()
                if prev_response <> response.text:
                    logger.debug('Reponse changed to %s', response.text)
                prev_response = response.text
                if json_data['meta']['total_count']:
                    if json_data['objects'][0]['message'] in steps:
                        steps.remove(json_data['objects'][0]['message'])
                    if json_data['objects'][0]['message'] == 'COMPLETE':
                        break
            time.sleep(.1)
        self.assertEqual(len(steps), 0,
                         'Did not get expected message(s) %s' % (steps, ))

        response = client.get(job_uri, params={'format': 'json'})
        json_response = response.json()
        self.assertTrue(
            json_response['status'] in ('Post-processing results', 'Complete'),
            'Expected a status of Complete, not %s' %
            (json_response['status']))

        timeout = time.time() + 120
        while time.time() < timeout:
            if json_response['status'] == 'Complete':
                break
            response = client.get(job_uri, params={'format': 'json'})
            json_response = response.json()
            time.sleep(.1)
        else:
            self.fail(
                'Expected status to be complete after 120s timeout, not %s' %
                (json_response['status']))
        results_uri = None
        for row in json_response['results_files']:
            if row['primary']:
                logger.debug("Primary results were %s", row)
                results_uri = client.getURL(path=row['datafile'])
        if not results_uri:
            self.fail(
                'Expected to get back a primary result, none found in %s' %
                (json_response, ))
        # Try to see if another user can download this job or results..
        username2, password2 = self.getUsernamePassword()
        user_uri = self._create_user(username2, password2)
        client2 = NMTKClient(self.site_url)
        client2.login(username=username2, password=password2)
        response = client2.get(job_uri, params={'format': 'json'})
        self.assertEqual(response.status_code, 401,
                         ('Expected 401 forbidden when ' +
                          'another user tried to get job info (not %s)') %
                         (response.status_code, ))
        response = client2.get(results_uri, params={'format': 'json'})
        self.assertEqual(response.status_code, 401,
                         ('Expected 401 forbidden when ' +
                          'another user tried to get result (not %s)') %
                         (response.status_code, ))

        response = client.get(results_uri, params={'format': 'json'})
        self.assertEqual(
            response.status_code, 200,
            'Status code expected was 200, not %s' % (response.status_code, ))
        logger.debug('Header is %s', response.headers)

        data = json.loads(response.content)
Exemplo n.º 12
0
    def test_create_delete_user(self):
        '''
        Verify that we can create a user via the API, and delete a user via the API
        In this case we will also validate that users, once deleted, are 
        effectively neutered via the UI.  The same is true for a logged in user
        whose account is deleted while the user is logged in.
        '''
        payload = {'format': 'json', 'limit': 999, 'all': True}
        response = self.client.get(self.api_user_url, params=payload)
        user_count = response.json()['meta']['total_count']
        # Create the user
        username, password = self.getUsernamePassword()
        response = self._create_user(username, password)
        self.assertEqual(
            201, response.status_code,
            'Expected status code of 201, not %s' % (response.status_code))
        user_uri = response.headers['location']
        response = self.client.get(user_uri, params=payload)
        self.assertEqual(
            response.status_code, 200,
            'Expected to get user data, not %s (%s)' %
            (response.status_code, response.text))
        logger.debug('Response was %s', response.json())
        # Get a list of users, verifying that user is there
        response = self.client.get(self.api_user_url, params=payload)

        json_data = response.json()
        # Verify we have one more user than before
        self.assertEqual(
            user_count + 1, json_data['meta']['total_count'],
            'Final count of users is %s, expected %s' %
            (json_data['meta']['total_count'], user_count + 1))
        # Verify that the user we created exists
        usernames = [rec['username'] for rec in json_data['objects']]
        self.assertTrue(
            username in usernames,
            'Username %s not found in %s' % (username, ','.join(usernames)))

        # Verify we can get the user via a query
        payload2 = payload.copy()
        payload2['username'] = username
        response = self.client.get(self.api_user_url, params=payload2)
        json_data = response.json()
        logger.debug('Response was %s', response.text)
        self.assertEqual(
            1, json_data['meta']['total_count'],
            'Retrieve record for ONLY %s, got %s records back' %
            (username, json_data['meta']['total_count']))

        # Verify that the user we created exists (just copy the check from above,
        # because I am lazy - and this works the same)
        usernames = [rec['username'] for rec in json_data['objects']]
        self.assertTrue(
            username in usernames,
            'Username %s not found in %s' % (username, ','.join(usernames)))

        # MAke sure that meta wasn't lying, and we really only got one record back.
        self.assertEqual(len(usernames),
                         1,
                         msg='More than one user returned from query')

        # Verify we can login as the newly created user.
        client = NMTKClient(self.site_url)
        response = client.login(username, password)
        logger.debug('Response from login was %s', response.status_code)
        self.assertEqual(response.status_code, 302,
                         'Login did not produce expected redirect')
        self.assertTrue(len(response.headers.get('location')),
                        'Redirect location header expected, not provided')
        response = client.get(client.getURL(path=''), allow_redirects=False)
        self.assertEqual(200, response.status_code,
                         'Unexpected redirect retrieving protected URI')

        # Delete the user we just created
        response = self._delete_user(user_uri)
        self.assertEqual(204, response.status_code)

        # Try to access a protected URL
        response = client.get(client.getURL(path=self.protected_url),
                              allow_redirects=False)
        self.assertEqual(
            302, response.status_code,
            'Deleted user should not be able to access a' + ' protected URI')

        # Try to login again as the disabled user:
        client = NMTKClient(self.site_url)
        response = client.login(username, password)
        self.assertEqual(200, response.status_code,
                         'Login for deleted user should fail')

        response = client.get(client.getURL(path=self.protected_url),
                              allow_redirects=False)
        self.assertEqual(
            302, response.status_code,
            'Deleted user should not be able to access a' + ' protected URI')
Exemplo n.º 13
0
 def test_create_delete_user(self):
     '''
     Verify that we can create a user via the API, and delete a user via the API
     In this case we will also validate that users, once deleted, are 
     effectively neutered via the UI.  The same is true for a logged in user
     whose account is deleted while the user is logged in.
     '''
     payload={'format': 'json',
              'limit': 999,
              'all': True }
     response=self.client.get(self.api_user_url, params=payload)
     user_count=response.json()['meta']['total_count']
     # Create the user
     username, password=self.getUsernamePassword()
     response=self._create_user(username, password)
     self.assertEqual(201, response.status_code,
                      'Expected status code of 201, not %s' % 
                      (response.status_code))
     user_uri=response.headers['location']
     response=self.client.get(user_uri, params=payload)
     self.assertEqual(response.status_code, 200, 'Expected to get user data, not %s (%s)'%
                      (response.status_code, response.text))
     logger.debug('Response was %s', response.json())
     # Get a list of users, verifying that user is there
     response=self.client.get(self.api_user_url, params=payload)
     
     json_data=response.json()
     # Verify we have one more user than before
     self.assertEqual(user_count+1, json_data['meta']['total_count'],
                      'Final count of users is %s, expected %s' % 
                      (json_data['meta']['total_count'],
                       user_count+1))
     # Verify that the user we created exists
     usernames=[rec['username'] for rec in json_data['objects']]
     self.assertTrue(username in usernames, 
                     'Username %s not found in %s' % 
                     (username, ','.join(usernames)))
     
     # Verify we can get the user via a query
     payload2=payload.copy()
     payload2['username']= username
     response=self.client.get(self.api_user_url, params=payload2)
     json_data=response.json()
     logger.debug('Response was %s', response.text)
     self.assertEqual(1, json_data['meta']['total_count'],
                      'Retrieve record for ONLY %s, got %s records back' % 
                      (username,
                       json_data['meta']['total_count']))
     
     # Verify that the user we created exists (just copy the check from above,
     # because I am lazy - and this works the same)
     usernames=[rec['username'] for rec in json_data['objects']]
     self.assertTrue(username in usernames, 
                     'Username %s not found in %s' % 
                     (username, ','.join(usernames)))
     
     # MAke sure that meta wasn't lying, and we really only got one record back.
     self.assertEqual(len(usernames),1,msg='More than one user returned from query')
     
     # Verify we can login as the newly created user.
     client=NMTKClient(self.site_url)
     response=client.login(username, password)
     logger.debug('Response from login was %s', response.status_code)
     self.assertEqual(response.status_code,302,
                      'Login did not produce expected redirect')
     self.assertTrue(len(response.headers.get('location')),
                     'Redirect location header expected, not provided')
     response=client.get(client.getURL(path=''),
                         allow_redirects=False)
     self.assertEqual(200, response.status_code,
                      'Unexpected redirect retrieving protected URI')
             
     # Delete the user we just created
     response=self._delete_user(user_uri)
     self.assertEqual(204, response.status_code)
     
     # Try to access a protected URL
     response=client.get(client.getURL(path=self.protected_url),
                         allow_redirects=False)
     self.assertEqual(302, response.status_code,
                      'Deleted user should not be able to access a' +
                      ' protected URI')
     
     # Try to login again as the disabled user:
     client=NMTKClient(self.site_url)
     response=client.login(username, password)
     self.assertEqual(200, response.status_code,
                      'Login for deleted user should fail')
     
     response=client.get(client.getURL(path=self.protected_url),
                         allow_redirects=False)
     self.assertEqual(302, response.status_code,
                      'Deleted user should not be able to access a' +
                      ' protected URI')
Exemplo n.º 14
0
class NMTKTestCase(unittest.TestCase):

    def _id_generator(self, size=6,
                      chars=(string.ascii_lowercase +
                             string.ascii_uppercase +
                             string.digits)):
        return ''.join(random.choice(chars) for x in range(size))

    def getUsernamePassword(self):
        return (self._id_generator(), self._id_generator())

    def getClient(self):
        return NMTKClient(self.site_url,
                          verify_ssl=self.verify_ssl)

    def _getSiteConfigDynamic(self):
        try:
            command = ['python',
                       self.settings_command,
                       'create_config']
            proc = subprocess.Popen(command, stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            out, err = proc.communicate()
            config = json.loads(err)
            self.delusers.append(config['username'])
            # Stderr contains the config output.
            return config
        except Exception as e:
            logger.exception('Failed to get dynamic config!')

        return None

    def _getSiteConfigStatic(self):
        config_file = os.path.join(nmtk_path, 'tests/config.json')
        if os.path.exists(config_file):
            try:
                config = json.loads(open(config_file).read())
                return config
            except:
                pass
        return None

    def _getSiteConfig(self):
        config = self._getSiteConfigDynamic() or self._getSiteConfigStatic()
        if config:
            return config
        raise Exception('No valid config found (tried both dynamic and static')

    def getNMTKClient(self, *args, **kwargs):
        return NMTKClient(self.site_url,
                          verify_ssl=self.verify_ssl)

    def setUp(self):
        self.settings_command = os.path.join(nmtk_path,
                                             'NMTK_apps/manage.py')
        self.delusers = []
        config = self._getSiteConfig()

        self.support_files = os.path.join(nmtk_path, 'tests/support_files')
        self.site_url = config['site_url']
        self.username = config['username']
        self.password = config['password']
        self.verify_ssl = config['verify_ssl']
        self.client = NMTKClient(self.site_url,
                                 verify_ssl=self.verify_ssl)
        self.client.login(self.username, self.password)
        self.api_user_url = self.client.getURL('api', 'user/')
        self.api_file_url = self.client.getURL('api', 'datafile/')

    def get_support_file(self, fn):
        return os.path.join(self.support_files, fn)

    def tearDown(self):
        '''
        Use the management purge_users command to purge the users created
        during testing from the database.
        '''
        if self.delusers:
            command = ['python',
                       self.settings_command,
                       'purge_users'] + self.delusers
            with open(os.devnull, "w") as fnull:
                subprocess.call(command, stdout=fnull, stderr=fnull)

    def _create_user(self, *args, **kwargs):
        '''
        A helper method to create a new user, given a password and userid
        '''
        if len(args) == 2:
            kwargs['username'] = args[0]
            kwargs['password'] = args[1]
        for key in ('username', 'password'):
            kwargs.setdefault(key, self._id_generator())

        response = self.client.create_user(**kwargs)
        self.delusers.append(kwargs['username'])
        return response

    def _delete_user(self, url):
        response = self.client.delete(url)
        logger.debug('Deleted %s with status code of %s',
                     url, response.status_code)
        return response
Exemplo n.º 15
0
    def test_submit_job(self):
        '''
        Verify that we can properly submit a job (form) via the API and \
get back the (eventual) results and status of the running job.  Also ensure other \
users cannot download results.
        '''
        username, password=self.getUsernamePassword()
        user_uri=self._create_user(username,password)
        client=NMTKClient(self.site_url)
        response=client.login(username=username,
                              password=password)
        filename=self.get_support_file('test1.geojson')
        test_file=client.uploadData(filename, 
                                    description='Test data file (MSP)')
        logger.debug('URI of test file is %s', test_file)
        
        tool_url=client.getURL('api','tool/')
        job_url=client.getURL('api','job/')
        response=client.get(tool_url, params={'format': 'json'})
        tools=response.json()['objects']

        # Get a list of all the Tool Resource URIs for Minnesota models,
        # since the test1.geojson file is a MN model-specific data file.
        for tool in tools:
            if 'umn' in tool['name'].lower():
                tool_uri=tool['resource_uri']
                break
        data={'tool': client.neuter_url(tool_uri),
              'description': 'Test job for testing by the automated test!'}
        
        response=client.post(job_url, 
                             data=json.dumps(data),
                             headers={'Content-Type': 'application/json',})
        #logger.debug('Result from post was %s', response.text)
        self.assertEqual(response.status_code, 201,
                         ('Expected job to be created - ' +
                          'got back %s instead') % (response.status_code,))
        job_uri=response.headers['location']
        
        # Now we have a job, let's get the form, generate the response, and
        # submit it back to the user.
        payload={ "config": { "coefficients": {"Arterial_coeff": { "type": "number",
                                                                   "value": 391.8 },
                                               "BusRoute_coeff": { "type": "number",
                                                                   "value": 100.3 },
                                               "CBDdist_km_coeff": { "type": "number",
                                                                     "value": -40.3 },
                                               "Collector_coeff": { "type": "number",
                                                                    "value": 611.1 },
                                               "Crime_coeff": { "type": "number",
                                                                "value": 2.9 },
                                               "EmployAccess_coeff": { "type": "number",
                                                                       "value": 0 },
                                               "LUMix_coeff": { "type": "number",
                                                                "value": -919.9 },
                                               "MedHHInc_coeff": { "type": "number",
                                                                   "value": 2.1 },
                                               "OffstreetTrail_coeff": { "type": "number",
                                                                         "value": 253.8  },
                                               "PDperkm2_coeff": { "type": "number",
                                                                   "value": -0.035  },
                                               "PctU5_O65_coeff": { "type": "number",
                                                                    "value": 32.5 },
                                               "Pctnonwhite_coeff": { "type": "number",
                                                                      "value": -29.8 },
                                               "Pctw4ormore_coeff": { "type": "number",
                                                                      "value": 371.4  },
                                               "Precip_coeff": { "type": "number",
                                                                 "value": -127.8 },
                                               "Principal_coeff": { "type": "number",
                                                                    "value": 66.4 },
                                               "Tmax_coeff": { "type": "number",
                                                               "value": -26 },
                                               "WatDist_km_coeff": { "type": "number",
                                                                     "value": -21.6 },
                                               "Year_coeff": { "type": "number",
                                                               "value": -5.9 },
                                               "constant": { "type": "number",
                                                             "value": 788.6 }
                                               },
                             "data": { "Arterial": { "type": "property",
                                                     "value": "Arterial" },
                                      "BusRoute": { "type": "property",
                                                    "value": "BusRoute" },
                                      "CBDdist_km": { "type": "property",
                                                      "value": "CBDdist_km" },
                                      "Collector": { "type": "property",
                                                     "value": "Collector" },
                                      "Crime": { "type": "property",
                                                 "value": "Crime" },
                                      "EmployAccess": { "type": "property",
                                                        "value": "EmployAccess" },
                                      "LUMix": { "type": "property",
                                                 "value": "LUMix" },
                                      "MedHHInc": { "type": "property",
                                                    "value": "MedHHInc" },
                                      "OffstreetTrail": { "type": "property",
                                                          "value": "OffstreetTrail" },
                                      "PDperkm2": { "type": "property",
                                                    "value": "PDperkm2" },
                                      "PctU5_O65": { "type": "property",
                                                     "value": "PctU5_O65" },
                                      "Pctnonwhite": { "type": "property",
                                                       "value": "Pctnonwhite" },
                                      "Pctw4ormore": { "type": "property",
                                                       "value": "Pctw4ormore" },
                                      "Principal": { "type": "property",
                                                     "value": "Principal" },
                                      "WatDist_km": { "type": "property",
                                                     "value": "WatDist_km" }
                                      },
                             "results": { "result": { "type": "string",
                                                      "value": "ped12ols" }
                                         }
                             },
                 "file_config": {
                                 "data": test_file
                                 }
                 }
        data=client.get(job_uri,
                        params={'format': 'json'}).json()
        data.update(payload)
        job_id=data['id']

        response=client.put(job_uri, 
                            headers={'Content-Type': 'application/json',},
                            data=json.dumps(data))
        logger.debug('Response from job update was %s', response.text)
        self.assertTrue(response.status_code in (204,202),
                         'Expected a return code of 204/202 with valid ' + 
                         'data provided got (%s)' % (response.status_code))
        
        # Now check the status to wait for completion
        timeout=time.time() + 120
        status_url=client.getURL('api','job_status/')
        params={'job': job_id,
                'format': 'json',
                'limit': 1 }
        steps=['Parameter & data file validation complete.','COMPLETE']
        prev_response=''
        while time.time() < timeout:
            response=client.get(status_url, params=params)
            self.assertEqual(response.status_code, 200,
                             'Expected to get valid response back')
            if len(response.text):
                json_data=response.json()
                if prev_response <> response.text:
                    logger.debug('Reponse changed to %s', response.text)
                prev_response=response.text
                if json_data['meta']['total_count']:
                    if json_data['objects'][0]['message'] in steps:
                        steps.remove(json_data['objects'][0]['message'])
                    if json_data['objects'][0]['message']=='COMPLETE':
                        break
            time.sleep(.1)
        self.assertEqual(len(steps),0, 
                         'Did not get expected message(s) %s' % (steps,))
        
        response=client.get(job_uri, params={'format': 'json'})
        json_response=response.json()
        self.assertTrue(json_response['status'] in ('Post-processing results', 'Complete'),
                         'Expected a status of Complete, not %s' % (json_response['status']))
        
        timeout=time.time() + 120
        while time.time() < timeout:
            if json_response['status'] == 'Complete':
                break
            response=client.get(job_uri, params={'format': 'json'})
            json_response=response.json()
            time.sleep(.1)
        else:
            self.fail('Expected status to be complete after 120s timeout, not %s' % (json_response['status']))
        results_uri=None
        for row in json_response['results_files']:
            if row['primary']:
                logger.debug("Primary results were %s", row)
                results_uri=client.getURL(path=row['datafile'])
        if not results_uri:
            self.fail('Expected to get back a primary result, none found in %s' % (json_response,))
        # Try to see if another user can download this job or results..
        username2, password2=self.getUsernamePassword()
        user_uri=self._create_user(username2,password2)
        client2=NMTKClient(self.site_url)
        client2.login(username=username2,
                      password=password2)
        response=client2.get(job_uri, params={'format': 'json'})
        self.assertEqual(response.status_code, 401,
                         ('Expected 401 forbidden when ' +
                          'another user tried to get job info (not %s)') % (response.status_code,))
        response=client2.get(results_uri, 
                             params={'format': 'json'})
        self.assertEqual(response.status_code, 401,
                         ('Expected 401 forbidden when ' +
                          'another user tried to get result (not %s)') % (response.status_code,))
        
        response=client.get(results_uri, 
                            params={'format': 'json'})
        self.assertEqual(response.status_code, 200,
                         'Status code expected was 200, not %s' % (response.status_code,))
        logger.debug('Header is %s', response.headers)

        data=json.loads(response.content)
Exemplo n.º 16
0
class NMTKTestCase(unittest.TestCase):

    def _id_generator(self, size=6,
                      chars=(string.ascii_lowercase +
                             string.ascii_uppercase +
                             string.digits)):
        return ''.join(random.choice(chars) for x in range(size))

    def getUsernamePassword(self):
        return (self._id_generator(), self._id_generator())

    def _getSiteConfigDynamic(self):
        try:
            command = ['python',
                       self.settings_command,
                       'create_config']
            proc = subprocess.Popen(command, stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            out, err = proc.communicate()
            config = json.loads(err)
            self.delusers.append(config['username'])
            # Stderr contains the config output.
            return config
        except Exception as e:
            logger.exception('Failed to get dynamic config!')

        return None

    def _getSiteConfigStatic(self):
        config_file = os.path.join(nmtk_path, 'tests/config.json')
        if os.path.exists(config_file):
            try:
                config = json.loads(open(config_file).read())
                return config
            except:
                pass
        return None

    def _getSiteConfig(self):
        config = self._getSiteConfigDynamic() or self._getSiteConfigStatic()
        if config:
            return config
        raise Exception('No valid config found (tried both dynamic and static')

    def setUp(self):
        self.settings_command = os.path.join(nmtk_path,
                                             'NMTK_apps/manage.py')
        self.delusers = []
        config = self._getSiteConfig()

        self.support_files = os.path.join(nmtk_path, 'tests/support_files')
        self.site_url = config['site_url']
        self.username = config['username']
        self.password = config['password']
        self.client = NMTKClient(self.site_url)
        self.client.login(self.username, self.password)
        self.api_user_url = self.client.getURL('api', 'user/')
        self.api_file_url = self.client.getURL('api', 'datafile/')

    def get_support_file(self, fn):
        return os.path.join(self.support_files, fn)

    def tearDown(self):
        '''
        Use the management purge_users command to purge the users created
        during testing from the database.
        '''
        if self.delusers:
            command = ['python',
                       self.settings_command,
                       'purge_users'] + self.delusers
            with open(os.devnull, "w") as fnull:
                subprocess.call(command, stdout=fnull, stderr=fnull)

    def _create_user(self, *args, **kwargs):
        '''
        A helper method to create a new user, given a password and userid
        '''
        if len(args) == 2:
            kwargs['username'] = args[0]
            kwargs['password'] = args[1]
        for key in ('username', 'password'):
            kwargs.setdefault(key, self._id_generator())

        response = self.client.create_user(**kwargs)
        self.delusers.append(kwargs['username'])
        return response

    def _delete_user(self, url):
        response = self.client.delete(url)
        logger.debug('Deleted %s with status code of %s',
                     url, response.status_code)
        return response