Exemple #1
0
class TaskQueueTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', None)

    def test_worker(self):
        # noinspection PyArgumentList
        awesome_task = AwesomeTask()
        self.session.add(awesome_task)

        another_task = AnotherTask()
        self.session.add(another_task)

        bad_task = BadTask()
        self.session.add(bad_task)

        self.session.commit()

        tasks = worker(tries=0, filters=Task.type == 'awesome_task')
        self.assertEqual(len(tasks), 1)
        self.assertTrue(awesome_task_done.is_set())
        self.assertFalse(another_task_done.is_set())

        self.session.refresh(awesome_task)
        self.assertEqual(awesome_task.status, 'success')

        tasks = worker(tries=0, filters=Task.type == 'bad_task')
        self.assertEqual(len(tasks), 1)
        bad_task_id = tasks[0][0]
        self.session.refresh(bad_task)
        self.assertEqual(bad_task.status, 'failed')

        tasks = worker(tries=0, filters=Task.type == 'bad_task')
        self.assertEqual(len(tasks), 0)

        # Reset the status of one task
        self.session.refresh(bad_task)
        bad_task.status = 'in-progress'
        self.session.commit()
        self.session.refresh(bad_task)

        Task.reset_status(bad_task_id, self.session)
        self.session.commit()
        tasks = worker(tries=0, filters=Task.type == 'bad_task')
        self.assertEqual(len(tasks), 1)

        tasks = worker(tries=0, filters=Task.type == 'bad_task')
        self.assertEqual(len(tasks), 0)

        # Cleanup all tasks
        Task.cleanup(self.session, statuses=('in-progress', 'failed'))
        self.session.commit()

        tasks = worker(tries=0, filters=Task.type == 'bad_task')
        self.assertEqual(len(tasks), 1)

        tasks = worker(tries=0, filters=Task.type == 'bad_task')
        self.assertEqual(len(tasks), 0)

        # Doing all remaining tasks
        tasks = worker(tries=0)
        self.assertEqual(len(tasks), 1)
class ApproveRequiredMixinTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', None)
    __configuration__ = '''
    db:
      url: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_approve_required_mixin(self):
        # noinspection PyArgumentList
        object1 = ApproveRequiredObject(title='object 1', )

        DBSession.add(object1)
        DBSession.commit()
        self.assertFalse(object1.is_approved)
        self.assertEqual(
            DBSession.query(ApproveRequiredObject).filter(
                ApproveRequiredObject.is_approved).count(), 0)

        object1.is_approved = True
        self.assertTrue(object1.is_approved)
        DBSession.commit()
        object1 = DBSession.query(ApproveRequiredObject).one()
        self.assertTrue(object1.is_approved)

        json = object1.to_dict()
        self.assertIn('isApproved', json)

        self.assertEqual(
            DBSession.query(ApproveRequiredObject).filter(
                ApproveRequiredObject.is_approved).count(), 1)
        self.assertEqual(ApproveRequiredObject.filter_approved().count(), 1)

        self.assertFalse(
            ApproveRequiredObject.import_value(
                ApproveRequiredObject.is_approved, 'false'))
        self.assertFalse(
            ApproveRequiredObject.import_value(
                ApproveRequiredObject.is_approved, 'FALSE'))
        self.assertFalse(
            ApproveRequiredObject.import_value(
                ApproveRequiredObject.is_approved, 'False'))
        self.assertTrue(
            ApproveRequiredObject.import_value(
                ApproveRequiredObject.is_approved, 'true'))
        self.assertTrue(
            ApproveRequiredObject.import_value(
                ApproveRequiredObject.is_approved, 'TRUE'))
        self.assertTrue(
            ApproveRequiredObject.import_value(
                ApproveRequiredObject.is_approved, 'True'))

        self.assertEqual(
            ApproveRequiredObject.import_value(ApproveRequiredObject.title,
                                               'title'), 'title')
class ValidationPreventFormTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', Root())

    @classmethod
    def configure_app(cls):
        super().configure_app()
        settings.merge("""
            logging:
              loggers:
                default:
                  level: info
            """)

    def test_validation_prevent_form(self):
        # Good
        self.request('All', 'POST', '/validation', doc=False)

        # Bad
        self.request('All',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'param': 'param'},
                     expected_status=400)
        self.request('All',
                     'POST',
                     '/validation',
                     doc=False,
                     query_string={'param': 'param'},
                     expected_status=400)
class OrderableCheckingModelTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', None)
    __configuration__ = '''
    db:
      uri: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_orderable_mixin(self):

        for i in range(3):
            # noinspection PyArgumentList
            instance = OrderableCheckingModel(
                title='test title %s' % i,
                order=i
            )
            DBSession.add(instance)
            DBSession.commit()

        instances = OrderableCheckingModel.apply_default_sort().all()
        self.assertEqual(instances[0].order, 0)
        self.assertEqual(instances[2].order, 2)
class CommitDecoratorTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', Root())
    __configuration__ = '''
    db:
      uri: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_commit_decorator(self):
        self.request('ALL', 'POST', '/', params=dict(title='first'), doc=False)
        resp, ___ = self.request('ALL', 'GET', '/first', doc=False)
        self.assertEqual(resp['title'], 'first')
        self.assertEqual(resp['id'], 1)

    def test_commit_decorator_and_json_patch(self):
        # The commit decorator should not to do anything if the request is a jsonpatch.
        self.request('ALL',
                     'PATCH',
                     '/',
                     doc=False,
                     json=[
                         dict(op='post', path='', value=dict(title='second')),
                         dict(op='post', path='', value=dict(title='third'))
                     ])
        resp, ___ = self.request('ALL', 'GET', '/third', doc=False)
        self.assertEqual(resp['title'], 'third')

    def test_rollback(self):
        self.request('ALL', 'ERROR', '/', doc=False, expected_status=500)
Exemple #6
0
class PaginationMixinTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', None)
    __configuration__ = '''
    db:
      url: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_pagination_mixin(self):
        for i in range(1, 6):
            # noinspection PyArgumentList
            obj = PagingObject(
                title='object %s' % i,
            )
            DBSession.add(obj)
        DBSession.commit()

        with Context({'QUERY_STRING': 'take=2&skip=1'}, self.application) as context:
            self.assertEqual(PagingObject.paginate_by_request().count(), 2)
            self.assertEqual(context.response_headers['X-Pagination-Take'], '2')
            self.assertEqual(context.response_headers['X-Pagination-Skip'], '1')
            self.assertEqual(context.response_headers['X-Pagination-Count'], '5')

        with Context({'QUERY_STRING': 'take=two&skip=one'}, self.application):
            self.assertEqual(PagingObject.paginate_by_request().count(), 4)

        with Context({'QUERY_STRING': 'take=5'}, self.application):
            self.assertRaises(HttpBadRequest, PagingObject.paginate_by_request)
Exemple #7
0
class FullTextSearchMixinTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', None)
    __configuration__ = '''
    db:
      uri: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_fts_escape(self):
        result = fts_escape('&%!^$*[](){}\\')
        self.assertEqual(result, '\&\%\!\^\$\*\[\]\(\)\{\}\\\\')

    def test_to_tsvector(self):
        result = to_tsvector('a', 'b', 'c')
        self.assertEqual(str(result),
                         'to_tsvector(:to_tsvector_1, :to_tsvector_2)')

    def test_activation_mixin(self):
        # noinspection PyArgumentList
        query = FullTextSearchObject.search('a')
        self.assertEqual(
            str(query).replace('\n', ' '),
            'SELECT fulltext_search_object.id AS fulltext_search_object_id, fulltext_search_object.title AS '
            'fulltext_search_object_title  FROM fulltext_search_object  WHERE to_tsvector(%(to_tsvector_1)s, '
            'fulltext_search_object.title) @@ to_tsquery(%(to_tsvector_2)s)')
Exemple #8
0
def oauth_mockup_server(root_controller):
    app = MockupApplication('mockup-oauth', root_controller)
    with http_server(app) as (server, url):
        settings.merge(f'''
            tokenizer:
              url: {url}
        ''')
        yield app
class ApplicationTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', Root())

    def test_index(self):
        response, headers = self.request('ALL', 'GET', '/')
        self.assertEqual(response, b'Index')

    def test_options(self):
        response, headers = self.request('ALL', 'OPTIONS', '/')
        self.assertEqual(headers['Cache-Control'], 'no-cache,no-store')
Exemple #10
0
class EtagCheckingModelTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', Root())
    __configuration__ = '''
    db:
      url: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_etag_match(self):
        resp, headers = self.request(
            'ALL', 'POST', '/', params=[FormParameter('title', 'etag_test')])
        self.assertIn('ETag', headers)
        initial_etag = headers['ETag']

        # Getting the resource with known etag, expected 304
        self.request('ALL',
                     'GET',
                     '/etag_test',
                     headers={'If-None-Match': initial_etag},
                     expected_status=304)

        # Putting without the etag header, expected error: Precondition Failed
        self.request('ALL',
                     'PUT',
                     '/etag_test',
                     params=[FormParameter('title', 'etag_test_edit1')],
                     expected_status=412)

        # Putting with the etag header, expected: success
        resp, headers = self.request(
            'ALL',
            'PUT',
            '/etag_test',
            params=[FormParameter('title', 'etag_test_edit1')],
            headers={'If-Match': initial_etag})
        self.assertIn('ETag', headers)
        etag_after_put = headers['ETag']
        self.assertNotEqual(initial_etag, etag_after_put)

        # Getting the resource with known etag, expected 304
        self.request('ALL',
                     'GET',
                     '/etag_test_edit1',
                     headers={'If-None-Match': initial_etag},
                     expected_status=200)
        self.assertIn('ETag', headers)
        new_etag = headers['ETag']
        self.assertNotEqual(new_etag, initial_etag)
        self.assertEqual(new_etag, etag_after_put)
Exemple #11
0
class OrderingMixinTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', None)
    __configuration__ = '''
    db:
      uri: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_ordering_mixin(self):
        for i in range(1, 6):
            # noinspection PyArgumentList
            obj = OrderableOrderingObject(title='object %s' % i, age=i * 10)
            DBSession.add(obj)

            # noinspection PyArgumentList
            obj = OrderingObject(title='object %s' % i, )
            DBSession.add(obj)
        DBSession.commit()

        # Default soring with Orderable objects
        with Context({'QUERY_STRING': ''}, self.application):
            result = OrderableOrderingObject.sort_by_request().all()
            self.assertEqual(result[0].id, 1)
            self.assertEqual(result[-1].id, 5)

        # Default soring without Orderable objects
        with Context({'QUERY_STRING': ''}, self.application):
            result = OrderingObject.sort_by_request().all()
            self.assertEqual(len(result), 5)

        # Ascending
        with Context({'QUERY_STRING': 'sort=id'}, self.application):
            result = OrderableOrderingObject.sort_by_request().all()
            self.assertEqual(result[0].id, 1)
            self.assertEqual(result[-1].id, 5)

        # Descending
        with Context({'QUERY_STRING': 'sort=-id'}, self.application):
            result = OrderableOrderingObject.sort_by_request().all()
            self.assertEqual(result[0].id, 5)
            self.assertEqual(result[-1].id, 1)

        # Sort by Synonym Property
        with Context({'QUERY_STRING': 'sort=age'}, self.application):
            result = OrderableOrderingObject.sort_by_request().all()
            self.assertEqual(result[0].id, 1)
            self.assertEqual(result[-1].id, 5)
class ModificationCheckingModelTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', None)
    __configuration__ = '''
    db:
      url: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_modified_mixin(self):

        # noinspection PyArgumentList
        instance = ModificationCheckingModel(
            title='test title',
        )

        DBSession.add(instance)
        DBSession.commit()
        self.assertIsNone(instance.modified_at)
        self.assertIsNotNone(instance.created_at)
        self.assertEqual(instance.last_modification_time, instance.created_at)

        instance = DBSession.query(ModificationCheckingModel).one()
        self.assertIsNone(instance.modified_at)
        self.assertIsNotNone(instance.created_at)
        self.assertEqual(instance.last_modification_time, instance.created_at)

        instance.title = 'Edited title'
        DBSession.commit()
        self.assertIsNotNone(instance.modified_at)
        self.assertIsNotNone(instance.created_at)
        self.assertEqual(instance.last_modification_time, instance.modified_at)

        instance = DBSession.query(ModificationCheckingModel).one()
        self.assertIsNotNone(instance.modified_at)
        self.assertIsNotNone(instance.created_at)
        self.assertEqual(instance.last_modification_time, instance.modified_at)
Exemple #13
0
class ModelValidationDecoratorTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', Root())
    __configuration__ = '''
    db:
      url: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_model_validate_decorator(self):
        # Required
        self.request('ALL', 'POST', '/', params={}, expected_status=400)

        # Correct pattern
        resp, ___ = self.request('ALL',
                                 'POST',
                                 '/',
                                 params=dict(title='Test'),
                                 doc=False)
        self.assertEqual(resp['title'], 'Test')

        # Invalid pattern
        self.request('ALL',
                     'POST',
                     '/',
                     params=dict(title='startWithSmallCase'),
                     expected_status=400,
                     doc=False)

        # Readonly
        self.request('ALL',
                     'POST',
                     '/',
                     params=dict(title='Test',
                                 modified=datetime.now().isoformat()),
                     expected_status=400,
                     doc=False)
Exemple #14
0
class SoftDeleteCheckingModelTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', None)
    __configuration__ = '''
    db:
      uri: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_soft_delete_mixin(self):
        # noinspection PyArgumentList
        instance = SoftDeleteCheckingModel(title='test title')
        DBSession.add(instance)
        DBSession.commit()
        instance.assert_is_not_deleted()
        self.assertRaises(ValueError, instance.assert_is_deleted)

        instance = SoftDeleteCheckingModel.query.one()
        instance.soft_delete()
        DBSession.commit()
        instance.assert_is_deleted()
        self.assertRaises(ValueError, instance.assert_is_not_deleted)

        self.assertEqual(SoftDeleteCheckingModel.filter_deleted().count(), 1)
        self.assertEqual(SoftDeleteCheckingModel.exclude_deleted().count(), 0)

        instance.soft_undelete()
        DBSession.commit()
        instance.assert_is_not_deleted()
        self.assertRaises(ValueError, instance.assert_is_deleted)

        self.assertEqual(SoftDeleteCheckingModel.filter_deleted().count(), 0)
        self.assertEqual(SoftDeleteCheckingModel.exclude_deleted().count(), 1)

        DBSession.delete(instance)
        self.assertRaises(HttpConflict, DBSession.commit)
class MessagingModelTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', None)
    __configuration__ = '''
    db:
      uri: sqlite://    # In memory DB
      echo: false
      
    messaging:
      default_sender: [email protected]
      default_messenger: restfulpy.testing.helpers.MockupMessenger
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_messaging_model(self):
        mockup_messenger = create_messenger()

        # noinspection PyArgumentList
        message = Welcome(to='*****@*****.**',
                          subject='Test Subject',
                          body={'msg': 'Hello'})

        DBSession.add(message)
        DBSession.commit()

        message.do_({})

        # noinspection PyUnresolvedReferences
        self.assertDictEqual(
            mockup_messenger.last_message, {
                'body': {
                    'msg': 'Hello'
                },
                'subject': 'Test Subject',
                'to': '*****@*****.**'
            })
Exemple #16
0
class BaseModelTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', Root())
    __configuration__ = '''
    db:
      uri: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_update_from_request(self):
        resp, ___ = self.request('ALL',
                                 'POST',
                                 '/',
                                 params=dict(title='test',
                                             firstName='test',
                                             lastName='test',
                                             email='*****@*****.**',
                                             password='******',
                                             birth='01-01-01',
                                             weight=1.1),
                                 doc=False)
        self.assertEqual(resp['title'], 'test')

        resp, ___ = self.request('ALL', 'GET', '/', doc=False)
        self.assertEqual(len(resp), 1)
        self.assertEqual(resp[0]['title'], 'test')

        # 404
        self.request('ALL',
                     'GET',
                     '/non-existance-user',
                     doc=False,
                     expected_status=404)

        # Plain dictionary
        resp, ___ = self.request('ALL', 'GET', '/me', doc=False)
        self.assertEqual(resp['title'], 'me')

    def test_iter_columns(self):
        columns = {
            c.key: c
            for c in Member.iter_columns(
                relationships=False, synonyms=False, composites=False)
        }
        self.assertEqual(len(columns), 9)
        self.assertNotIn('name', columns)
        self.assertNotIn('password', columns)
        self.assertIn('_password', columns)

    def test_iter_json_columns(self):
        columns = {
            c.key: c
            for c in Member.iter_json_columns(include_readonly_columns=False,
                                              include_protected_columns=False)
        }
        self.assertEqual(len(columns), 8)
        self.assertNotIn('name', columns)
        self.assertNotIn('password', columns)
        self.assertNotIn('_password', columns)

    def test_metadata(self):
        resp, ___ = self.request('ALL', 'METADATA', '/', doc=False)
        self.assertIn('firstName', resp)
class FilteringMixinTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', None)
    __configuration__ = '''
    db:
      uri: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_filtering_mixin(self):
        for i in range(1, 6):
            # noinspection PyArgumentList
            obj = FilteringObject(
                title='object %s' % i,
            )
            DBSession.add(obj)
        DBSession.commit()

        # Bad Value
        with Context({'QUERY_STRING': 'id=1'}, self.application) as context:
            context.query_string['id'] = 1
            self.assertRaises(HttpBadRequest, FilteringObject.filter_by_request)

        # IN
        with Context({'QUERY_STRING': 'id=^1,2,3'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 3)

        # NOT IN
        with Context({'QUERY_STRING': 'id=!^1,2,3'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 2)

        # IN (error)
        with Context({'QUERY_STRING': 'id=^'}, self.application):
            self.assertRaises(HttpBadRequest, FilteringObject.filter_by_request)

        # Between
        with Context({'QUERY_STRING': 'id=~1,3'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 3)

        # IS NULL
        with Context({'QUERY_STRING': 'title=null'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 0)

        # IS NOT NULL
        with Context({'QUERY_STRING': 'title=!null'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 5)

        # LIKE
        with Context({'QUERY_STRING': 'title=%obj'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 5)

        with Context({'QUERY_STRING': 'title=%OBJ'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 0)

        # ILIKE
        with Context({'QUERY_STRING': 'title=%~obj'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 5)

        with Context({'QUERY_STRING': 'title=%~OBJ'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 5)

        # ==
        with Context({'QUERY_STRING': 'id=1'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 1)

        # !=
        with Context({'QUERY_STRING': 'id=!1'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 4)

        # >=
        with Context({'QUERY_STRING': 'id=>=2'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 4)

        # >
        with Context({'QUERY_STRING': 'id=>2'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 3)

        # <=
        with Context({'QUERY_STRING': 'id=<=3'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 3)

        # <
        with Context({'QUERY_STRING': 'id=<3'}, self.application):
            self.assertEqual(FilteringObject.filter_by_request().count(), 2)
Exemple #18
0
class ValidationPatternTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', Root())

    @classmethod
    def configure_app(cls):
        super().configure_app()
        settings.merge("""
            logging:
              loggers:
                default:
                  level: info
            """)

    def test_validation_pattern(self):
        # Test `pattern`
        # role -> All
        self.wsgi_app.jwt_token = DummyIdentity().dump().decode()
        self.request('All',
                     'POST',
                     '/validation',
                     doc=False,
                     params={
                         'patternedParam1': '0123456789',
                         'patternedParam2': 'abcdeFGHIJ',
                         'patternedParam3': 'Exact'
                     })

        self.request('All',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'patternedParam1': '12345'},
                     expected_status=400)

        # -----------------------------
        # role -> Client
        self.wsgi_app.jwt_token = DummyIdentity('client').dump().decode()
        self.request('Client',
                     'POST',
                     '/validation',
                     doc=False,
                     params={
                         'patternedParam1': '12345',
                         'patternedParam2': 'ABCDE',
                         'patternedParam3': 'Exact',
                         'patternedParam4': 'anything'
                     })

        self.request('Client',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'patternedParam1': '1'},
                     expected_status=400)

        # -----------------------------
        # role -> Admin
        self.wsgi_app.jwt_token = DummyIdentity('admin').dump().decode()
        self.request('Admin',
                     'POST',
                     '/validation',
                     doc=False,
                     params={
                         'patternedParam1': '1',
                         'patternedParam2': 'ABCDEFGHIJ',
                         'patternedParam4': 'SuperAdmin'
                     })

        self.request('Admin',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'patternedParam4': 'anything'},
                     expected_status=400)
class StatefulAuthenticatorTestCase(WebAppTestCase):
    application = MockupApplication(
        'MockupApplication',
        Root(),
        authenticator=MockupStatefulAuthenticator())

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge("""
            jwt:
              max_age: .3
              refresh_token:
                max_age: 3
        """)

    def test_invalidate_token(self):
        response, headers = self.request('ALL',
                                         'GET',
                                         '/login',
                                         json=dict(email='*****@*****.**',
                                                   password='******'))
        refresh_token = headers['Set-Cookie'].split('; ')[0]
        self.assertIn('token', response)
        self.assertTrue(refresh_token.startswith('refresh-token='))

        # Login on client
        token = response['token']
        self.wsgi_app.jwt_token = token

        # Request a protected resource to ensure authenticator is working well
        response, ___ = self.request(As.member,
                                     'GET',
                                     '/me',
                                     headers={'Cookie': refresh_token})
        self.assertListEqual(response['roles'], roles)

        # Invalidating the token by server
        roles.append('god')
        response, headers = self.request(As.member,
                                         'GET',
                                         '/invalidate_token',
                                         headers={'Cookie': refresh_token})
        self.assertListEqual(response['roles'], roles)
        self.assertIn('X-New-JWT-Token', headers)

        # Invalidating the token by server after the token has been expired expired, with appropriate cookies.
        time.sleep(1)
        response, headers = self.request(As.member,
                                         'GET',
                                         '/invalidate_token',
                                         headers={'Cookie': refresh_token})
        self.assertIn('X-New-JWT-Token', headers)
        self.assertIsNotNone(headers['X-New-JWT-Token'])
        self.wsgi_app.jwt_token = headers['X-New-JWT-Token']
        self.request(As.member,
                     'GET',
                     '/me',
                     headers={'Cookie': refresh_token})

    def test_logout(self):
        response, headers = self.request('ALL',
                                         'POST',
                                         '/login',
                                         json=dict(email='*****@*****.**',
                                                   password='******'))
        self.assertIn('token', response)
        self.assertEqual(headers['X-Identity'], '1')
        self.wsgi_app.jwt_token = response['token']
        response, headers = self.request('ALL', 'DELETE', '/logout')
        self.assertNotIn('X-Identity', headers)

    def test_session_member(self):
        with Context(environ={}, application=self.application):
            principal = self.application.__authenticator__.login(
                ('*****@*****.**', 'test'))
            self.assertEqual(
                self.application.__authenticator__.get_session_member(
                    principal.session_id), 1)

    @freeze_time("2017-07-13T13:11:44", tz_offset=-4)
    def test_session_info(self):
        # Login
        response, headers = self.request('ALL',
                                         'GET',
                                         '/login',
                                         json=dict(email='*****@*****.**',
                                                   password='******'))
        self.wsgi_app.jwt_token = response['token']

        # Testing test cases
        for test_case in session_info_test_cases:
            # Our new session info should be updated
            payload, ___ = self.request(As.member,
                                        'GET',
                                        '/me',
                                        extra_environ=test_case['environment'])

            info = self.application.__authenticator__.get_session_info(
                payload['sessionId'])
            self.assertDictEqual(
                info, {
                    'remoteAddress': test_case['expected_remote_address'],
                    'machine': test_case['expected_machine'],
                    'os': test_case['expected_os'],
                    'agent': test_case['expected_agent'],
                    'client': test_case['expected_client'],
                    'app': test_case['expected_app'],
                    'lastActivity': test_case['expected_last_activity'],
                })
class ActivationMixinTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', None)
    __configuration__ = '''
    db:
      url: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)

    def test_activation_mixin(self):
        # noinspection PyArgumentList
        object1 = ActiveObject(title='object 1', )

        DBSession.add(object1)
        DBSession.commit()
        self.assertFalse(object1.is_active)
        self.assertEqual(
            DBSession.query(ActiveObject).filter(
                ActiveObject.is_active).count(), 0)

        object1.is_active = True
        self.assertTrue(object1.is_active)
        DBSession.commit()
        object1 = DBSession.query(ActiveObject).one()
        self.assertTrue(object1.is_active)

        json = object1.to_dict()
        self.assertIn('isActive', json)

        self.assertEqual(
            DBSession.query(ActiveObject).filter(
                ActiveObject.is_active).count(), 1)
        self.assertEqual(ActiveObject.filter_activated().count(), 1)

        self.assertFalse(
            ActiveObject.import_value(ActiveObject.is_active, 'false'))
        self.assertFalse(
            ActiveObject.import_value(ActiveObject.is_active, 'FALSE'))
        self.assertFalse(
            ActiveObject.import_value(ActiveObject.is_active, 'False'))
        self.assertTrue(
            ActiveObject.import_value(ActiveObject.is_active, 'true'))
        self.assertTrue(
            ActiveObject.import_value(ActiveObject.is_active, 'TRUE'))
        self.assertTrue(
            ActiveObject.import_value(ActiveObject.is_active, 'True'))
        self.assertEqual(
            ActiveObject.import_value(ActiveObject.title, 'title'), 'title')

    def test_auto_activation(self):
        # noinspection PyArgumentList
        object1 = AutoActiveObject(title='object 1', )

        DBSession.add(object1)
        DBSession.commit()
        self.assertTrue(object1.is_active)
        self.assertEqual(
            1,
            DBSession.query(AutoActiveObject).filter(
                AutoActiveObject.is_active).count())

    def test_metadata(self):
        # Metadata
        object_metadata = ActiveObject.json_metadata()
        self.assertIn('id', object_metadata['fields'])
        self.assertIn('title', object_metadata['fields'])
        self.assertIn('isActive', object_metadata['fields'])
class ValidationExactTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', Root())

    @classmethod
    def configure_app(cls):
        super().configure_app()
        settings.merge("""
            logging:
              loggers:
                default:
                  level: info
            """)

    def test_validation_exact(self):
        # Test `exact`
        # role -> All
        self.wsgi_app.jwt_token = DummyIdentity().dump().decode()
        result, ___ = self.request('All',
                                   'POST',
                                   '/validation',
                                   doc=False,
                                   params={'exactParamForAll': 'param'})
        self.request('All',
                     'POST',
                     '/validation',
                     doc=False,
                     expected_status=400)
        self.request('All',
                     'POST',
                     '/validation',
                     doc=False,
                     params={
                         'exactParamForAll': 'param',
                         'exactParamForCustom': 'param',
                     },
                     expected_status=400)
        self.request('All',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'exactParamForCustom': 'param'},
                     expected_status=400)
        self.assertIn('exactParamForAll', result)
        self.request('All',
                     'POST',
                     '/validation',
                     doc=False,
                     params={
                         'exactParamForAll': 'param',
                         'exactParamForClient': 'param',
                     },
                     expected_status=400)
        # -----------------------------
        # role -> Client
        self.wsgi_app.jwt_token = DummyIdentity('client').dump().decode()

        result, ___ = self.request('Client',
                                   'POST',
                                   '/validation',
                                   doc=False,
                                   params={
                                       'exactParamForAll': 'param',
                                       'exactParamForClient': 'param',
                                   })
        self.assertIn('exactParamForClient', result)
        self.assertIn('exactParamForAll', result)

        self.request('Client',
                     'POST',
                     '/validation',
                     doc=False,
                     params={
                         'exactParamForAll': 'param',
                         'exactParamForClient': 'param',
                         'exactParamForAdmin': 'param',
                     },
                     expected_status=400)

        # -----------------------------
        # role -> Admin
        self.wsgi_app.jwt_token = DummyIdentity('admin').dump().decode()

        result, ___ = self.request('Admin',
                                   'POST',
                                   '/validation',
                                   doc=False,
                                   params={
                                       'exactParamForAll': 'param',
                                       'exactParamForAdmin': 'param',
                                   })
        self.assertIn('exactParamForAdmin', result)
        self.assertIn('exactParamForAll', result)

        self.request('Admin',
                     'POST',
                     '/validation',
                     doc=False,
                     params={
                         'exactParamForAll': 'param',
                         'exactParamForClient': 'param',
                         'exactParamForAdmin': 'param',
                     },
                     expected_status=400)

        # ------------------------------------------------------------

        # Test query string
        self.wsgi_app.jwt_token = DummyIdentity('admin').dump().decode()
        result, ___ = self.request('Admin',
                                   'POST',
                                   '/validation',
                                   doc=False,
                                   query_string={
                                       'exactParamForAll': 'param',
                                   },
                                   params={
                                       'exactParamForAdmin': 'param',
                                   })
        self.assertIn('exactParamForAdmin', result)
        self.assertIn('exactParamForAll', result)

        self.request('Admin',
                     'POST',
                     '/validation',
                     doc=False,
                     query_string={
                         'exactParamForAll': 'param',
                         'exactParamForClient': 'param',
                     },
                     params={'exactParamForAdmin': 'param'},
                     expected_status=400)
class StatefulAuthenticatorTestCase(WebAppTestCase):
    application = MockupApplication(
        'MockupApplication',
        Root(),
        authenticator=MockupStatefulAuthenticator())

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge("""
            jwt:
              max_age: .3
              refresh_token:
                max_age: 3
        """)

    def test_invalidate_token(self):
        response, headers = self.request('ALL',
                                         'GET',
                                         '/login',
                                         json=dict(email='*****@*****.**',
                                                   password='******'))
        refresh_token = headers['Set-Cookie'].split('; ')[0]
        self.assertIn('token', response)
        self.assertTrue(refresh_token.startswith('refresh-token='))

        # Login on client
        token = response['token']
        self.wsgi_app.jwt_token = token

        # Request a protected resource to ensure authenticator is working well
        response, ___ = self.request(As.member,
                                     'GET',
                                     '/me',
                                     headers={'Cookie': refresh_token})
        self.assertListEqual(response['roles'], roles)

        # Invalidating the token by server
        roles.append('god')
        response, headers = self.request(As.member,
                                         'GET',
                                         '/invalidate_token',
                                         headers={'Cookie': refresh_token})
        self.assertListEqual(response['roles'], roles)
        self.assertIn('X-New-JWT-Token', headers)

        # Invalidating the token by server after the token has been expired expired, with appropriate cookies.
        time.sleep(1)
        response, headers = self.request(As.member,
                                         'GET',
                                         '/invalidate_token',
                                         headers={'Cookie': refresh_token})
        self.assertIn('X-New-JWT-Token', headers)
        self.assertIsNotNone(headers['X-New-JWT-Token'])
        self.wsgi_app.jwt_token = headers['X-New-JWT-Token']
        self.request(As.member,
                     'GET',
                     '/me',
                     headers={'Cookie': refresh_token})

    def test_logout(self):
        response, headers = self.request('ALL',
                                         'POST',
                                         '/login',
                                         json=dict(email='*****@*****.**',
                                                   password='******'))
        self.assertIn('token', response)
        self.assertEqual(headers['X-Identity'], '1')
        self.wsgi_app.jwt_token = response['token']
        response, headers = self.request('ALL', 'DELETE', '/logout')
        self.assertEqual(headers['X-Identity'], '')
Exemple #23
0
class BaseModelTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', Root())
    __configuration__ = '''
    db:
      url: sqlite://    # In memory DB
      echo: false
    '''

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge(cls.__configuration__)
        settings.merge('''
        logging:
          loggers:
            default:
              level: debug
        ''')

    def test_update_from_request(self):
        resp, ___ = self.request('ALL',
                                 'POST',
                                 '/',
                                 params=dict(
                                     title='test',
                                     firstName='test',
                                     lastName='test',
                                     email='*****@*****.**',
                                     password='******',
                                     birth='2001-01-01',
                                     weight=1.1,
                                     visible='false',
                                     lastLoginTime='2017-10-10T15:44:30.000',
                                     isActive=True),
                                 doc=False)
        self.assertEqual(resp['title'], 'test')

        resp, ___ = self.request('ALL',
                                 'GET',
                                 '/',
                                 query_string=dict(take=1),
                                 doc=False)
        self.assertEqual(len(resp), 1)
        self.assertEqual(resp[0]['title'], 'test')
        self.assertEqual(resp[0]['visible'], False)

        # 404
        self.request('ALL',
                     'GET',
                     '/non-existence-user',
                     doc=False,
                     expected_status=404)

        # Plain dictionary
        resp, ___ = self.request('ALL', 'GET', '/me', doc=False)
        self.assertEqual(resp['title'], 'me')

        # 400 for sending relationship attribute
        self.request('ALL',
                     'POST',
                     '/',
                     json=dict(title='test',
                               firstName='test',
                               lastName='test',
                               email='*****@*****.**',
                               password='******',
                               birth='2001-01-01',
                               weight=1.1,
                               visible='false',
                               lastLoginTime='2017-10-10T15:44:30.000',
                               isActive=True,
                               books=[]),
                     doc=False,
                     expected_status=400)

    def test_iter_columns(self):
        columns = {
            c.key: c
            for c in Member.iter_columns(
                relationships=False, synonyms=False, composites=False)
        }
        self.assertEqual(len(columns), 15)
        self.assertNotIn('name', columns)
        self.assertNotIn('password', columns)
        self.assertIn('_password', columns)

    def test_iter_json_columns(self):
        columns = {
            c.key: c
            for c in Member.iter_json_columns(include_readonly_columns=False,
                                              include_protected_columns=False)
        }
        self.assertEqual(len(columns), 13)
        self.assertNotIn('name', columns)
        self.assertNotIn('password', columns)
        self.assertNotIn('_password', columns)

    def test_metadata(self):
        resp, ___ = self.request('ALL', 'METADATA', '/', doc=False)

        self.assertIn('fields', resp)
        self.assertIn('name', resp)
        self.assertIn('primaryKeys', resp)
        self.assertIn('id', resp['primaryKeys'])
        self.assertEqual(resp['name'], 'Member')
        fields = resp['fields']
        self.assertIn('id', fields)
        self.assertIn('firstName', fields)
        self.assertEqual(fields['id']['primaryKey'], True)
        self.assertEqual(fields['email']['primaryKey'], False)
        self.assertEqual(fields['title']['primaryKey'], False)
        self.assertEqual(fields['title']['minLength'], 2)
        self.assertEqual(fields['title']['maxLength'], 50)
        self.assertEqual(fields['email']['pattern'],
                         '(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)')

        self.assertEqual(fields['firstName']['name'], 'firstName')
        self.assertEqual(fields['firstName']['key'], 'first_name')

        self.assertEqual(fields['firstName']['type_'], 'str')
        self.assertEqual(fields['birth']['type_'], 'date')

        self.assertEqual(fields['weight']['default_'], 50)
        self.assertEqual(fields['visible']['optional'], True)

        self.assertEqual(fields['email']['message'],
                         'Invalid email address, please be accurate!')
        self.assertEqual(fields['email']['watermark'], 'Email')
        self.assertEqual(fields['email']['label'], 'Email')
        self.assertEqual(fields['email']['icon'], 'email.svg')
        self.assertEqual(fields['email']['example'], '*****@*****.**')

    def test_datetime_format(self):
        # datetime allows contain microseconds
        self.request('ALL',
                     'POST',
                     '/',
                     params=dict(title='test',
                                 firstName='test',
                                 lastName='test',
                                 email='*****@*****.**',
                                 password='******',
                                 birth='2001-01-01',
                                 weight=1.1,
                                 visible='false',
                                 lastLoginTime='2017-10-10T10:10:00.12313'),
                     doc=False)
        self.request('ALL',
                     'POST',
                     '/',
                     params=dict(title='test',
                                 firstName='test',
                                 lastName='test',
                                 email='*****@*****.**',
                                 password='******',
                                 birth='2001-01-01',
                                 weight=1.1,
                                 visible='false',
                                 lastLoginTime='2017-10-10T10:10:00.'),
                     doc=False,
                     expected_status=400)

        self.request('ALL',
                     'POST',
                     '/',
                     params=dict(title='test',
                                 firstName='test',
                                 lastName='test',
                                 email='*****@*****.**',
                                 password='******',
                                 birth='2001-01-01',
                                 weight=1.1,
                                 visible='false',
                                 lastLoginTime='2017-10-10T10:10:00'),
                     doc=False)

        # Invalid month value
        self.request('ALL',
                     'POST',
                     '/',
                     params=dict(title='test',
                                 firstName='test',
                                 lastName='test',
                                 email='*****@*****.**',
                                 password='******',
                                 birth='2001-01-01',
                                 weight=1.1,
                                 visible='false',
                                 lastLoginTime='2017-13-10T10:10:00'),
                     doc=False,
                     expected_status=400)

        # Invalid datetime format
        self.request('ALL',
                     'POST',
                     '/',
                     params=dict(title='test',
                                 firstName='test',
                                 lastName='test',
                                 email='*****@*****.**',
                                 password='******',
                                 birth='2001-01-01',
                                 weight=1.1,
                                 visible='false',
                                 lastLoginTime='InvalidDatetime'),
                     doc=False,
                     expected_status=400)

        # datetime might not have ending Z
        resp, ___ = self.request('ALL',
                                 'POST',
                                 '/',
                                 params=dict(
                                     title='test',
                                     firstName='test',
                                     lastName='test',
                                     email='*****@*****.**',
                                     password='******',
                                     birth='2001-01-01',
                                     weight=1.1,
                                     visible='false',
                                     lastLoginTime='2017-10-10T10:10:00.4546'),
                                 doc=False)
        self.assertEqual(resp['lastLoginTime'], '2017-10-10T10:10:00.004546Z')

        # datetime containing ending Z
        resp, ___ = self.request(
            'ALL',
            'POST',
            '/',
            params=dict(title='test',
                        firstName='test',
                        lastName='test',
                        email='*****@*****.**',
                        password='******',
                        birth='2001-01-01',
                        weight=1.1,
                        visible='false',
                        lastLoginTime='2017-10-10T10:10:00.4546Z'),
            doc=False)
        self.assertEqual(resp['lastLoginTime'], '2017-10-10T10:10:00.004546Z')

    def test_date_format(self):
        # iso date format
        resp, ___ = self.request(
            'ALL',
            'POST',
            '/',
            params=dict(title='test',
                        firstName='test',
                        lastName='test',
                        email='*****@*****.**',
                        password='******',
                        birth='2001-01-01',
                        weight=1.1,
                        visible='false',
                        lastLoginTime='2017-10-10T10:10:00.4546Z'),
            doc=False)
        self.assertEqual(resp['birth'], '2001-01-01')
        self.assertEqual(resp['lastLoginTime'], '2017-10-10T10:10:00.004546Z')

        # posix timestamp
        resp, ___ = self.request('ALL',
                                 'POST',
                                 '/',
                                 params=dict(title='test',
                                             firstName='test',
                                             lastName='test',
                                             email='*****@*****.**',
                                             password='******',
                                             birth='1513434403',
                                             weight=1.1,
                                             visible='false',
                                             lastLoginTime=datetime(
                                                 2017, 10, 10, 10, 10, 0,
                                                 4546).timestamp()),
                                 doc=False)
        self.assertEqual(resp['birth'], '2017-12-16')
        self.assertEqual(resp['lastLoginTime'], '2017-10-10T10:10:00.004546Z')

        # none iso date format
        self.request('ALL',
                     'POST',
                     '/',
                     params=dict(title='test',
                                 firstName='test',
                                 lastName='test',
                                 email='*****@*****.**',
                                 password='******',
                                 birth='01-01-01',
                                 weight=1.1,
                                 visible='false',
                                 lastLoginTime='2017-10-10T10:10:00.4546Z'),
                     doc=False,
                     expected_status=400)

        # none iso date format
        self.request('ALL',
                     'POST',
                     '/',
                     params=dict(title='test',
                                 firstName='test',
                                 lastName='test',
                                 email='*****@*****.**',
                                 password='******',
                                 birth='2001/01/01',
                                 weight=1.1,
                                 visible='false',
                                 lastLoginTime='2017-10-10T10:10:00.4546Z'),
                     doc=False,
                     expected_status=400)
Exemple #24
0
class ValidationFilterTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', Root())

    @classmethod
    def configure_app(cls):
        super().configure_app()
        settings.merge("""
            logging:
              loggers:
                default:
                  level: info
            """)

    def test_validation_filter(self):
        # Test `filter`
        # role -> All
        self.wsgi_app.jwt_token = DummyIdentity().dump().decode()
        result, ___ = self.request('All',
                                   'POST',
                                   '/validation',
                                   doc=False,
                                   params={
                                       'customParam': 'param',
                                       'filteredParamForAll': 'param',
                                       'filteredParamForClient': 'param',
                                       'filteredParamForAdmin': 'param',
                                   })
        self.assertNotIn('customParam', result)
        self.assertNotIn('filteredParamForClient', result)
        self.assertNotIn('filteredParamForAdmin', result)
        self.assertIn('filteredParamForAll', result)
        # -----------------------------
        # role -> Client
        self.wsgi_app.jwt_token = DummyIdentity('client').dump().decode()
        result, ___ = self.request('Client',
                                   'POST',
                                   '/validation',
                                   doc=False,
                                   params={
                                       'customParam': 'param',
                                       'filteredParamForAll': 'param',
                                       'filteredParamForClient': 'param',
                                       'filteredParamForAdmin': 'param',
                                   })
        self.assertNotIn('customParam', result)
        self.assertIn('filteredParamForClient', result)
        self.assertNotIn('filteredParamForAdmin', result)
        self.assertIn('filteredParamForAll', result)
        # -----------------------------
        # role -> Admin
        self.wsgi_app.jwt_token = DummyIdentity('admin').dump().decode()
        result, ___ = self.request('Admin',
                                   'POST',
                                   '/validation',
                                   doc=False,
                                   params={
                                       'customParam': 'param',
                                       'filteredParamForAll': 'param',
                                       'filteredParamForClient': 'param',
                                       'filteredParamForAdmin': 'param',
                                   })
        self.assertNotIn('customParam', result)
        self.assertNotIn('filteredParamForClient', result)
        self.assertIn('filteredParamForAdmin', result)
        self.assertIn('filteredParamForAll', result)
class ValidationTypesTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', Root())

    @classmethod
    def configure_app(cls):
        super().configure_app()
        settings.merge("""
            logging:
              loggers:
                default:
                  level: info
            """)

    def test_validation_types(self):
        # Test `type`
        # role -> All
        self.wsgi_app.jwt_token = DummyIdentity().dump().decode()
        result, ___ = self.request(
            'All', 'POST', '/validation',
            doc=False,
            params={
                'typedParam1': '1',
                'typedParam2': '2',
                'typedParam3': '3',
                'typedParam4': '4'
            }
        )
        self.assertEqual(type(result['typedParam1']), float)
        self.assertEqual(type(result['typedParam2']), float)
        self.assertEqual(type(result['typedParam3']), float)
        self.assertEqual(type(result['typedParam4']), str)

        self.request(
            'All', 'POST', '/validation',
            doc=False,
            params={'typedParam1': 'not_convertible'},
            expected_status=400
        )

        # -----------------------------
        # role -> Client
        self.wsgi_app.jwt_token = DummyIdentity('client').dump().decode()
        result, ___ = self.request(
            'Client', 'POST', '/validation',
            doc=False,
            params={
                'typedParam1': '1',
                'typedParam2': '2',
                'typedParam3': '3',
                'typedParam4': '4'
            }
        )
        self.assertEqual(type(result['typedParam1']), int)
        self.assertEqual(type(result['typedParam2']), int)
        self.assertEqual(type(result['typedParam3']), float)
        self.assertEqual(type(result['typedParam4']), str)

        self.request(
            'Client', 'POST', '/validation',
            doc=False,
            params={'typedParam1': 'not_convertible'},
            expected_status=400
        )

        # -----------------------------
        # role -> Admin
        self.wsgi_app.jwt_token = DummyIdentity('admin').dump().decode()
        result, ___ = self.request(
            'Admin', 'POST', '/validation',
            doc=False,
            params={
                'typedParam1': '1',
                'typedParam2': '2',
                'typedParam3': '3',
                'typedParam4': '4'
            }
        )
        # type complex is dict
        self.assertEqual(type(result['typedParam1']), dict)
        self.assertEqual(type(result['typedParam2']), float)
        self.assertEqual(type(result['typedParam3']), float)
        self.assertEqual(type(result['typedParam4']), dict)

        self.request(
            'Admin', 'POST', '/validation',
            doc=False,
            params={'typedParam1': 'not_convertible'},
            expected_status=400
        )
class AuthenticatorTestCase(WebAppTestCase):
    application = MockupApplication(
        'MockupApplication',
        Root(),
        authenticator=MockupStatelessAuthenticator())

    @classmethod
    def configure_app(cls):
        cls.application.configure(force=True)
        settings.merge("""
            jwt:
              max_age: .8
              refresh_token:
                max_age: 2.2
        """)

    def test_login(self):
        response, headers = self.request('ALL',
                                         'POST',
                                         '/login',
                                         json=dict(email='*****@*****.**',
                                                   password='******'))
        self.assertIn('token', response)
        self.assertEqual(headers['X-Identity'], '1')

        self.wsgi_app.jwt_token = response['token']
        response, headers = self.request('ALL',
                                         'GET',
                                         '/',
                                         json=dict(a='a', b='b'))
        self.assertEqual(headers['X-Identity'], '1')

        # Broken token
        self.wsgi_app.jwt_token = self.wsgi_app.jwt_token[:-10]
        self.request('ALL', 'GET', '/', expected_status=400)

        # Empty
        self.wsgi_app.jwt_token = ' '
        self.request('ALL', 'GET', '/me', expected_status=401)

        # Bad Password
        self.wsgi_app.jwt_token = None
        self.request('ALL',
                     'POST',
                     '/login',
                     json=dict(email='*****@*****.**', password='******'),
                     expected_status=400)

    def test_logout(self):
        response, headers = self.request('ALL',
                                         'POST',
                                         '/login',
                                         json=dict(email='*****@*****.**',
                                                   password='******'))
        self.assertIn('token', response)
        self.assertEqual(headers['X-Identity'], '1')
        self.wsgi_app.jwt_token = response['token']
        response, headers = self.request('ALL', 'DELETE', '/logout')
        self.assertEqual(headers['X-Identity'], '')

    def test_refresh_token(self):
        self.wsgi_app.jwt_token = None
        response, headers = self.request('ALL',
                                         'POST',
                                         '/login',
                                         json=dict(email='*****@*****.**',
                                                   password='******'))
        refresh_token = headers['Set-Cookie'].split('; ')[0]
        self.assertIn('token', response)
        self.assertTrue(refresh_token.startswith('refresh-token='))

        # Login on client
        token = response['token']
        self.wsgi_app.jwt_token = token
        time.sleep(1.1)

        # Request a protected resource after the token has been expired expired, with broken cookies
        self.request(As.member,
                     'GET',
                     '/me',
                     headers={'Cookie': 'refresh-token=broken-data'},
                     expected_status=400)

        # Request a protected resource after the token has been expired expired, with empty cookies
        self.request(As.member,
                     'GET',
                     '/me',
                     headers={'Cookie': 'refresh-token='},
                     expected_status=401)

        # Request a protected resource after the token has been expired expired, without the cookies
        self.request(As.member, 'GET', '/me', expected_status=401)

        # Request a protected resource after the token has been expired expired, with appropriate cookies.
        response, response_headers = self.request(
            As.member, 'GET', '/me', headers={'Cookie': refresh_token})
        self.assertIn('X-New-JWT-Token', response_headers)
        self.assertIsNotNone(response_headers['X-New-JWT-Token'])

        # Test with invalid Refresh Token
        self.request(As.member,
                     'GET',
                     '/me',
                     headers={'Cookie': 'refresh-token=InvalidToken'},
                     expected_status=400)

        # Waiting until expire refresh token
        time.sleep(3)
        # Request a protected resource after the refresh-token has been expired.
        self.request(As.member,
                     'GET',
                     '/me',
                     headers={'Cookie': refresh_token},
                     expected_status=401)

    def test_authorization(self):
        response, headers = self.request('ALL',
                                         'POST',
                                         '/login',
                                         json=dict(email='*****@*****.**',
                                                   password='******'))
        self.assertIn('token', response)
        self.assertEqual(headers['X-Identity'], '1')
        self.wsgi_app.jwt_token = response['token']
        response, headers = self.request('ALL',
                                         'GET',
                                         '/kill',
                                         expected_status=403)
        self.assertEqual(headers['X-Identity'], '1')
Exemple #27
0
class ValidationBlackListTestCase(WebAppTestCase):
    application = MockupApplication('MockupApplication', Root())

    @classmethod
    def configure_app(cls):
        super().configure_app()
        settings.merge("""
            logging:
              loggers:
                default:
                  level: info
            """)

    def test_validation_blacklist(self):
        # Test `blacklist`
        # role -> All
        self.wsgi_app.jwt_token = DummyIdentity().dump().decode()
        self.request('All', 'POST', '/validation', doc=False)
        self.request('All',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'customParam': 'param'})
        self.request('All',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'blacklistParamForAll': 'param'},
                     expected_status=400)
        self.request('All',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'blacklistParamForClient': 'param'})
        self.request('All',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'blacklistParamForAdmin': 'param'})
        # -----------------------------
        # role -> Client
        self.wsgi_app.jwt_token = DummyIdentity('client').dump().decode()
        self.request('Client', 'POST', '/validation', doc=False)
        self.request('Client',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'customParam': 'param'})
        self.request('Client',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'blacklistParamForAll': 'param'},
                     expected_status=400)
        self.request('Client',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'blacklistParamForClient': 'param'},
                     expected_status=400)
        self.request('Client',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'blacklistParamForAdmin': 'param'})
        # -----------------------------
        # role -> Admin
        self.wsgi_app.jwt_token = DummyIdentity('admin').dump().decode()
        self.request('Admin', 'POST', '/validation', doc=False)
        self.request('Admin',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'customParam': 'param'})
        self.request('Admin',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'blacklistParamForAll': 'param'},
                     expected_status=400)
        self.request('Admin',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'blacklistParamForClient': 'param'})
        self.request('Admin',
                     'POST',
                     '/validation',
                     doc=False,
                     params={'blacklistParamForAdmin': 'param'},
                     expected_status=400)