Varad
Varad

Reputation: 1022

How can I set the value for request.authenticated_userid in pyramid framework of python

I am getting an error when I try to set the attribute for authenticated_userid as a request parameter. Its actually a nosetest I am using to mock up the request and see the response.

Traceback (most recent call last):
  File "/web/core/pulse/wapi/tests/testWapiUtilities_integration.py", line 652, in setUp
    setattr(self.request, 'authenticated_userid', self.data['user'].id)
AttributeError: can't set attribute

Code is as below

@attr(can_split=False)
class logSuspiciousRequestAndRaiseHTTPError(IntegrationTestCase):
    def setUp(self):
        super(logSuspiciousRequestAndRaiseHTTPError, self).setUp()
        from pyramid.request import Request
        from pyramid.threadlocal import get_current_registry
        request = Request({
            'SERVER_PROTOCOL': 'testprotocol',
            'SERVER_NAME': 'test server name',
            'SERVER_PORT': '80',
        })
        request.context = TestContext()
        request.root = request.context
        request.subpath = ['path']
        request.traversed = ['traversed']
        request.view_name = 'test view name'
        request.path_info = 'test info'
        request.scheme = 'https'
        request.host = 'test.com'
        request.registry = get_current_registry()
        self.request = request
        self.data = {}
        self.createDefaultData()
        self.request.userAccount = self.data['user'].userAccount

    # @unittest.skip('Pre-Demo skip. Need to mock userAccountModel')
    @mock.patch('pulse.wapi.wapiUtilities.pyramid.threadlocal.get_current_request')
    @mock.patch('pulse.wapi.wapiUtilities.securityLog')
    def testHasRequest_raises400AndLogsError(
            self, securityLog, get_current_request):
        # Arrange
        get_current_request.return_value = self.request

        with self.assertRaises(exception.HTTPBadRequest):
            from pulse.wapi.wapiUtilities import logSuspiciousRequestAndRaiseHTTPError
            logSuspiciousRequestAndRaiseHTTPError()
            self.assertTrue(securityLog.called)
            self.assertTrue(securityLog.return_value.info.called)

I am creating a dummy request and I am adding attributes to request.

When this method logSuspiciousRequestAndRaiseHTTPError() is called the request is parsed by the method to get user account.

userAccountID=authenticated_userid(self.request)

This returns None since the request doesn't have an attribute self.request.authenticated_userid

Please let me know if you need any additional information.

Upvotes: 4

Views: 1547

Answers (3)

Erdős-Bacon
Erdős-Bacon

Reputation: 908

Because authenticated_userid is a reified attribute coming from the underlying authentication policy, it can not be directly set in the DummyRequest when doing a test. This means both of the below will not work:

# Will NOT work
dummy_request = DummyRequest(authenticated_userid='mock_user')
# Also will NOT work
dummy_request = DummyRequest()
dummy_request.authenticated_userid = 'mock_user'

Instead, if we want to be able to control the authenticated_userid for a test (or other aspects of the auth policies as well), we need to change the underlying Pyramid config for the test we're running. For this, you'll want to take a look at pyramid.testing.setUp (docs here). This returns a config object that can do a whole bunch of things, but the important one for our interests is the testing_securitypolicy method (docs here).

testing_securitypolicy allows us to have pretty granular control over how requests will be seen from an auth point of view. Look at its docs for specifics, but with it we can set what the authenticated_userid will be for a request, make it so that permission requirements are ignored, and more.

Here's an example of usage in a test:

from pyramid.testing import (setUp, tearDown, DummyRequest)

def test_some_view():
    config = setUp()
    config.testing_securitypolicy(userid='mock_user')  # Sets authenticated_userid

    dummy_request = DummyRequest()
    print(dummy_request.authenticated_userid)  # Prints 'mock_user'

    # Now ready to test something that uses request.authenticated_userid
    from mypyramidapp.views.secure import some_auth_view
    result = some_auth_view(dummy_request)
    expected = 'Hello mock_user!'
    assert result == expected

    # Finally, to avoid security changes leaking to other tests, use tearDown
    tearDown()  # Undo the effects of pyramid.testing.setUp()

Upvotes: 1

Varad
Varad

Reputation: 1022

Finally I got the solution.

I added self.config = testing.setUp()

self.config.testing_securitypolicy(
    userid=self.data['user'].userAccount.id, permissive=True
)

Added the userAccountId as mock up value for testing security policy.

@attr(can_split=False)
class logSuspiciousRequestAndRaiseHTTPError(IntegrationTestCase):
    def setUp(self):
        super(logSuspiciousRequestAndRaiseHTTPError, self).setUp()
        from pyramid.request import Request
        from pyramid.threadlocal import get_current_registry
        self.config = testing.setUp()
        request = Request({
            'SERVER_PROTOCOL': 'testprotocol',
            'SERVER_NAME': 'test server name',
            'SERVER_PORT': '80',
        })
        request.context = TestContext()
        request.root = request.context
        request.subpath = ['path']
        request.traversed = ['traversed']
        request.view_name = 'test view name'
        request.path_info = 'test info'
        request.scheme = 'https'
        request.host = 'test.com'
        request.registry = get_current_registry()
        self.request = request
        self.data = {}
        self.createDefaultData()
        self.request.userAccount = self.data['user'].userAccount

    @mock.patch('pulse.wapi.wapiUtilities.pyramid.threadlocal.get_current_request')
    @mock.patch('pulse.wapi.wapiUtilities.securityLog')
    def testHasRequest_raises400AndLogsError(
            self, securityLog, get_current_request):
        # Arrange
        get_current_request.return_value = self.request
        self.loggedInUser = self.data['user']
        self.config.testing_securitypolicy(
            userid=self.data['user'].userAccount.id, permissive=True
        )

        with self.assertRaises(exception.HTTPBadRequest):
            from pulse.wapi.wapiUtilities import logSuspiciousRequestAndRaiseHTTPError
            logSuspiciousRequestAndRaiseHTTPError()
            self.assertTrue(securityLog.called)
            self.assertTrue(securityLog.return_value.info.called)

Upvotes: 3

Mikko Ohtamaa
Mikko Ohtamaa

Reputation: 83368

authenticated_userid is reified attribute set by authentication framework.

See Logins with authentication for basic information.

Please include more code how you set up your request, as in its current form the question does not have details to give accurate answer.

Upvotes: 1

Related Questions