예제 #1
0
 def test_uses_ttl_from_settings_if_assertion_is_in_old_format(self):
     # This assertion comes from PyBrowserID tests cases.
     # https://github.com/mozilla/PyBrowserID
     assertion = """
     eyJjZXJ0aWZpY2F0ZXMiOlsiZXlKaGJHY2lPaUpTVXpFeU9DSjkuZXlKcGMzTWlPaUppY
     205M2MyVnlhV1F1YjNKbklpd2laWGh3SWpveE16SXhPVFF4T1Rnek1EVXdMQ0p3ZFdKc2
     FXTXRhMlY1SWpwN0ltRnNaMjl5YVhSb2JTSTZJbEpUSWl3aWJpSTZJamd4TmpreE5UQTB
     OVGswTkRVek5EVTFPREF4TlRreU5Ea3hNemsyTkRFNE56RTJNVFUwTkRNNE5EWXdPREl6
     TXpBMU1USXlPRGN3TURRNE56TTFNREk1TURrek16a3lNRFkzTURFMU1qQTBORGd6TWpVM
     U56WXdOREE1TnpFeU9EYzNNVGswT1RVek1UQXdNVFEyTkRVek56TTJOakU0TlRVek5EY3
     hNakkxT0RreU16TTFPRFV4TWpZNU1EQXdOREF5TVRrMk9ERTBNRGtpTENKbElqb2lOalU
     xTXpjaWZTd2ljSEpwYm1OcGNHRnNJanA3SW1WdFlXbHNJam9pY25saGJrQnlabXN1YVdR
     dVlYVWlmWDAua19oaEtYMFRCVnUyX2szbV9uRDVOVWJfTktwX19PLTY1MW1CRUl3S1NZZ
     GlOenQwQm9WRkNEVEVueEhQTWJCVjJaejk0WDgtLVRjVXJidEV0MWV1S1dWdjMtNTFUOU
     xBZnV6SEhfekNCUXJVbmxkMVpXSmpBM185ZEhQeTMwZzRMSU9YZTJWWmd0T1Nva3MyZFE
     4ZDNvazlSUTJQME5ERzB1MDBnN3lGejE4Il0sImFzc2VydGlvbiI6ImV5SmhiR2NpT2lK
     U1V6WTBJbjAuZXlKbGVIQWlPakV6TWpFNU1qazBOelU0TWprc0ltRjFaQ0k2SW1oMGRIQ
     TZMeTl0ZVdaaGRtOXlhWFJsWW1WbGNpNXZjbWNpZlEuQWhnS2Q0eXM0S3FnSGJYcUNSS3
     hHdlluVmFJOUwtb2hYSHk0SVBVWDltXzI0TWdfYlU2aGRIMTNTNnFnQy1vSHBpS3BfTGl
     6cDRGRjlUclBjNjBTRXcifQ
     """.replace(" ", "").replace("\n", "").strip()
     self.request.headers = {AUTHORIZATION_HEADER: 'Browserid ' + assertion,
                             CLIENT_STATE_HEADER: '12345'}
     self.request.registry.cache.flush()
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.encrypt',
                         return_value='encrypted'):
             with mock.patch.object(self.request.registry.cache, 'set') \
                     as mocked_set:
                 build_sync_client(self.request)
                 args, _ = tuple(mocked_set.call_args_list[-1])
                 ttl = args[-1]
                 self.assertEqual(int(ttl), 300)
    def test_statsd_time_token_server_call(self):
        with mock.patch('requests.request'):
            self.mocked_client.timer()().return_value = self.credentials

            with mock.patch('syncto.authentication.SyncClient'):
                build_sync_client(self.request)
                self.mocked_client.timer.assert_any_call(
                    'tokenserver.tokenserverclient.get_hawk_credentials')
예제 #3
0
 def test_should_return_the_client_if_everything_is_fine(self):
     self.request.headers = {AUTHORIZATION_HEADER: 'Browserid 1234',
                             CLIENT_STATE_HEADER: '12345'}
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.SyncClient') as SyncClient:
             build_sync_client(self.request)
             TSClient.assert_called_with(
                 '1234', '12345', 'https://token.services.mozilla.com/')
             SyncClient.assert_called_with(**self.credentials)
 def test_should_client_state_in_url_is_used_to_setup_sync_client(self):
     request = self.request
     request.headers = {AUTHORIZATION_HEADER: 'Browserid 1234'}
     request.matchdict['bucket_id'] = '601c4497372419ee1789bf931f8c68f5'
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.SyncClient') as SyncClient:
             build_sync_client(request)
             TSClient.assert_called_with(
                 '1234', '601c4497372419ee1789bf931f8c68f5',
                 'https://token.services.mozilla.com/', verify=None)
             SyncClient.assert_called_with(verify=None, **self.credentials)
    def test_uses_ttl_from_assertion_if_smaller_than_settings(self):
        assertion = """
        eyJhbGciOiJSUzI1NiJ9.eyJwdWJsaWMta2V5Ijp7ImFsZ29yaXRobSI6IkRTIiwiZyI6I
        jY3ZTU4NjQ2MGYzMzMyNjliNzlhZmJjZDA4MmYzNjk5NGMxNGNjZGMwYWQ5NWNhMmNmMWQ
        4MTZjMjVkZTQ5MmRiMTI2ZDkwOTc2ZmNmMWY3YWIxMmE4MTRkMTEwYzEzZWI0YmY1MjliM
        2M3ZmE3MDViYWVkZTcyZmI5ZTY5YmYzNzMzOTkwMjYzZDMwM2I4M2YyMGM4Nzg0OGI3YTg
        zMTg3ZWQzNjYwZTY0MThlOGY4YzAwNTE2ZWY5MGJlZmY0ODAyM2E1ZDc0NzllMjA1MGRiM
        2FlNjBhYWZkOWRkNGEyODk1NmNiNWVlNzRmMDA0NDc2MWQ4MTc1YmQ0NTYzOSIsInEiOiJ
        lMDc1YTgxMzEwNzAxZGFmNGE3M2E0MTRhYWJmNmNmZTRjZmI2M2UzIiwicCI6IjljYjFkZ
        jA4N2RjMjQ5YzEyZmRhOWFkYmY2YTE4MGQ0MDZmZTUwOGJjNjI3NzEyMGRkZDdmYzRhYjU
        xMThmYWY0ZjhmM2MyNTVmYWYwY2UyNGIzMjU5NWEwZmNkNjc1MTc0NmZiZDdmMzNjZWVlM
        TFhOWM2NTBjN2JkMDE3NTk1ZjBiOWMxOGY3NTEyMjg5MTI4YzQ1NjQzYTA3MjAxNGM1MGN
        jNWIxMDM4MDhkNmVmNTcwMWFiY2Q1ODAzMDgxYjIxNTIwNGI5OTIzNzNkYWIxZDVhMjdmM
        2NiMDFjNmY4NThkZDhkNzc3ZWZjZTgwNmRhYmI2YjgyNWMxYjU3ZTciLCJ5IjoiOTYyZWQ
        1ODE5NDcyMmNiMDQxNmE1M2E3OWQ2ZWEzOGIxYmQ2MmIxYzk2NWEwNGJmM2MzY2Q2MDQ3Y
        jVmZjBkMGFmZWEyYmE5ZjU0YjFkODE5M2UxN2FhZjVlYWE3NzUwMDBiMDVjZTQ2YmNmZTY
        wMzcyMTJkODI5YWFjYWRjNzFhMTA1MTMwNDk5ZGM2OWIzMzEwZTJkYzIxODAyYTQzNWFiY
        jU0M2IwOTFmY2U1NTVmYWRiNGQyZGNiZjVjN2MxNmQ5OTU0N2QwNWMwZDAwZDhkMGJmOTJ
        lMDE2M2UxNTRiYzQ0MmZhNTRjOGYwN2MxMjU4MzRlZDJhZDIyNmFiYiJ9LCJwcmluY2lwY
        WwiOnsiZW1haWwiOiI0NjY1NWQxMDQyNTU0OTYzOWFhZTI5N2M2ZmM2ZDYzMkBhcGkuYWN
        jb3VudHMuZmlyZWZveC5jb20ifSwiaWF0IjoxNDQ0MTIyNTczNTgwLCJleHAiOjE0NDQxM
        jQzODM1ODAsImZ4YS1nZW5lcmF0aW9uIjoxNDQ0MTIyNTA4ODM2LCJmeGEtbGFzdEF1dGh
        BdCI6MTQ0NDEyMjU4MiwiZnhhLXZlcmlmaWVkRW1haWwiOiJzeW5jdG9AcmVzdG1haWwub
        mV0IiwiaXNzIjoiYXBpLmFjY291bnRzLmZpcmVmb3guY29tIn0.39sRjyvQyEXgoWDHTzi
        J7LDfp8HqMyLIVXlCri0-SOSJq2QzKEdG0R3MKEdYMhH20dLKRqTqOmt1UiG1vw3XTUhHe
        5BOmjpQxMBRLoHSXWSIrfk0OCAPVdHIRVDOarNkaD7AYJ0ADdYMpx-EHov7N3tKVGOfURn
        _BwuM55dw7j6xeK_Qpy9iYRK59ApIlEFlxyWH4fAPvs45tThnJVwXjuBP1Bezt7O6SbLzv
        4lgZdDRdBrEnMA6YyLrJsV1_balKy9AQkT8Ye7lsHp9ysgdf6FiSvsvWOM_ZQaRy6V8lTq
        Ue9yTXyd5Ex5aJO62neLo-TZZ4beHNHd-XqBhkkb2bQ~eyJhbGciOiAiRFMxMjgifQ.eyJ
        hdWQiOiAiaHR0cHM6Ly90b2tlbi5zZXJ2aWNlcy5tb3ppbGxhLmNvbS8iLCAiZXhwIjogM
        TQ0NDEyNjE4MzAwMH0.i_0cKFEKNvRiGETGp8xNXH_JDEGsdhqguKGlcdCWeHr_EyUlUsh
        vnw""".replace(" ", "").replace("\n", "").strip()
        self.request.registry.settings.update(
            {'syncto.cache_credentials_ttl_seconds': 3600})

        self.request.headers = {
            AUTHORIZATION_HEADER: 'Browserid ' + assertion,
            CLIENT_STATE_HEADER: '12345'
        }
        self.request.registry.cache.flush()
        with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
            TSClient.return_value.get_hawk_credentials.return_value = \
                self.credentials
            with mock.patch('syncto.authentication.encrypt',
                            return_value='encrypted'):
                with mock.patch.object(self.request.registry.cache, 'set') \
                        as mocked_set:
                    build_sync_client(self.request)
                    args, _ = tuple(mocked_set.call_args_list[-1])
                    ttl = args[-1]
                    self.assertNotEqual(int(ttl), 3600)
예제 #6
0
 def test_should_decrypt_credentials(self):
     self.request.headers = {AUTHORIZATION_HEADER: 'Browserid 1234',
                             CLIENT_STATE_HEADER: '12345'}
     with mock.patch.object(
             self.request.registry.cache, 'get',
             return_value=ENCRYPTED_CREDENTIALS):
         with mock.patch('requests.request'):
             with mock.patch('syncto.authentication.decrypt',
                             return_value=json.dumps(self.credentials)) \
                     as mocked_decrypt:
                 build_sync_client(self.request)
                 mocked_decrypt.assert_called_with(ENCRYPTED_CREDENTIALS,
                                                   '12345',
                                                   'This is not a secret')
예제 #7
0
    def test_uses_ttl_from_assertion_if_smaller_than_settings(self):
        assertion = """
        eyJhbGciOiJSUzI1NiJ9.eyJwdWJsaWMta2V5Ijp7ImFsZ29yaXRobSI6IkRTIiwiZyI6I
        jY3ZTU4NjQ2MGYzMzMyNjliNzlhZmJjZDA4MmYzNjk5NGMxNGNjZGMwYWQ5NWNhMmNmMWQ
        4MTZjMjVkZTQ5MmRiMTI2ZDkwOTc2ZmNmMWY3YWIxMmE4MTRkMTEwYzEzZWI0YmY1MjliM
        2M3ZmE3MDViYWVkZTcyZmI5ZTY5YmYzNzMzOTkwMjYzZDMwM2I4M2YyMGM4Nzg0OGI3YTg
        zMTg3ZWQzNjYwZTY0MThlOGY4YzAwNTE2ZWY5MGJlZmY0ODAyM2E1ZDc0NzllMjA1MGRiM
        2FlNjBhYWZkOWRkNGEyODk1NmNiNWVlNzRmMDA0NDc2MWQ4MTc1YmQ0NTYzOSIsInEiOiJ
        lMDc1YTgxMzEwNzAxZGFmNGE3M2E0MTRhYWJmNmNmZTRjZmI2M2UzIiwicCI6IjljYjFkZ
        jA4N2RjMjQ5YzEyZmRhOWFkYmY2YTE4MGQ0MDZmZTUwOGJjNjI3NzEyMGRkZDdmYzRhYjU
        xMThmYWY0ZjhmM2MyNTVmYWYwY2UyNGIzMjU5NWEwZmNkNjc1MTc0NmZiZDdmMzNjZWVlM
        TFhOWM2NTBjN2JkMDE3NTk1ZjBiOWMxOGY3NTEyMjg5MTI4YzQ1NjQzYTA3MjAxNGM1MGN
        jNWIxMDM4MDhkNmVmNTcwMWFiY2Q1ODAzMDgxYjIxNTIwNGI5OTIzNzNkYWIxZDVhMjdmM
        2NiMDFjNmY4NThkZDhkNzc3ZWZjZTgwNmRhYmI2YjgyNWMxYjU3ZTciLCJ5IjoiOTYyZWQ
        1ODE5NDcyMmNiMDQxNmE1M2E3OWQ2ZWEzOGIxYmQ2MmIxYzk2NWEwNGJmM2MzY2Q2MDQ3Y
        jVmZjBkMGFmZWEyYmE5ZjU0YjFkODE5M2UxN2FhZjVlYWE3NzUwMDBiMDVjZTQ2YmNmZTY
        wMzcyMTJkODI5YWFjYWRjNzFhMTA1MTMwNDk5ZGM2OWIzMzEwZTJkYzIxODAyYTQzNWFiY
        jU0M2IwOTFmY2U1NTVmYWRiNGQyZGNiZjVjN2MxNmQ5OTU0N2QwNWMwZDAwZDhkMGJmOTJ
        lMDE2M2UxNTRiYzQ0MmZhNTRjOGYwN2MxMjU4MzRlZDJhZDIyNmFiYiJ9LCJwcmluY2lwY
        WwiOnsiZW1haWwiOiI0NjY1NWQxMDQyNTU0OTYzOWFhZTI5N2M2ZmM2ZDYzMkBhcGkuYWN
        jb3VudHMuZmlyZWZveC5jb20ifSwiaWF0IjoxNDQ0MTIyNTczNTgwLCJleHAiOjE0NDQxM
        jQzODM1ODAsImZ4YS1nZW5lcmF0aW9uIjoxNDQ0MTIyNTA4ODM2LCJmeGEtbGFzdEF1dGh
        BdCI6MTQ0NDEyMjU4MiwiZnhhLXZlcmlmaWVkRW1haWwiOiJzeW5jdG9AcmVzdG1haWwub
        mV0IiwiaXNzIjoiYXBpLmFjY291bnRzLmZpcmVmb3guY29tIn0.39sRjyvQyEXgoWDHTzi
        J7LDfp8HqMyLIVXlCri0-SOSJq2QzKEdG0R3MKEdYMhH20dLKRqTqOmt1UiG1vw3XTUhHe
        5BOmjpQxMBRLoHSXWSIrfk0OCAPVdHIRVDOarNkaD7AYJ0ADdYMpx-EHov7N3tKVGOfURn
        _BwuM55dw7j6xeK_Qpy9iYRK59ApIlEFlxyWH4fAPvs45tThnJVwXjuBP1Bezt7O6SbLzv
        4lgZdDRdBrEnMA6YyLrJsV1_balKy9AQkT8Ye7lsHp9ysgdf6FiSvsvWOM_ZQaRy6V8lTq
        Ue9yTXyd5Ex5aJO62neLo-TZZ4beHNHd-XqBhkkb2bQ~eyJhbGciOiAiRFMxMjgifQ.eyJ
        hdWQiOiAiaHR0cHM6Ly90b2tlbi5zZXJ2aWNlcy5tb3ppbGxhLmNvbS8iLCAiZXhwIjogM
        TQ0NDEyNjE4MzAwMH0.i_0cKFEKNvRiGETGp8xNXH_JDEGsdhqguKGlcdCWeHr_EyUlUsh
        vnw""".replace(" ", "").replace("\n", "").strip()
        self.request.registry.settings.update({
            'syncto.cache_credentials_ttl_seconds': 3600})

        self.request.headers = {AUTHORIZATION_HEADER: 'Browserid ' + assertion,
                                CLIENT_STATE_HEADER: '12345'}
        self.request.registry.cache.flush()
        with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
            TSClient.return_value.get_hawk_credentials.return_value = \
                self.credentials
            with mock.patch('syncto.authentication.encrypt',
                            return_value='encrypted'):
                with mock.patch.object(self.request.registry.cache, 'set') \
                        as mocked_set:
                    build_sync_client(self.request)
                    args, _ = tuple(mocked_set.call_args_list[-1])
                    ttl = args[-1]
                    self.assertNotEqual(int(ttl), 3600)
 def test_should_client_state_in_url_is_used_to_setup_sync_client(self):
     request = self.request
     request.headers = {AUTHORIZATION_HEADER: 'Browserid 1234'}
     request.matchdict['bucket_id'] = '601c4497372419ee1789bf931f8c68f5'
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.SyncClient') as SyncClient:
             build_sync_client(request)
             TSClient.assert_called_with(
                 '1234',
                 '601c4497372419ee1789bf931f8c68f5',
                 'https://token.services.mozilla.com/',
                 verify=None)
             SyncClient.assert_called_with(verify=None, **self.credentials)
 def test_should_return_an_alert_if_client_state_header_is_used(self):
     self.request.headers = {AUTHORIZATION_HEADER: 'Browserid 1234',
                             CLIENT_STATE_HEADER: '12345'}
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.SyncClient'):
             build_sync_client(self.request)
             self.assertIn('Alert', self.request.response.headers)
             self.assertDictEqual(
                 json.loads(self.request.response.headers['Alert']),
                 {"url": "https://syncto.readthedocs.io/",
                  "message": "X-Client-State header is deprecated "
                  "and should not be provided anymore.",
                  "code": "soft-eol"})
예제 #10
0
def collection_get(request):
    collection_name = request.matchdict['collection_name']
    sync_client = build_sync_client(request)

    headers = import_headers(request)

    params = {}
    if '_since' in request.GET:
        try:
            params['newer'] = '%.2f' % (int(request.GET['_since']) / 1000.0)
        except ValueError:
            error_msg = ("_since should be a number.")
            raise_invalid(request,
                          location="querystring",
                          name="_since",
                          description=error_msg)

    if '_limit' in request.GET:
        params['limit'] = request.GET['_limit']

    if '_token' in request.GET:
        params['offset'] = request.GET['_token']

    if '_sort' in request.GET:
        if request.GET['_sort'] in ('-last_modified', 'newest'):
            params['sort'] = 'newest'

        elif request.GET['_sort'] in ('-sortindex', 'index'):
            params['sort'] = 'index'

        elif request.GET['_sort'] in ('last_modified', 'oldest'):
            params['sort'] = 'oldest'

        else:
            error_msg = ("_sort should be one of ('-last_modified', 'newest', "
                         "'-sortindex', 'index', 'last_modified', 'oldest')")
            raise_invalid(request,
                          location="querystring",
                          name="_sort",
                          description=error_msg)

    if 'in_ids' in request.GET:
        params['ids'] = [record_id.strip() for record_id in
                         request.GET['in_ids'].split(',') if record_id]

    records = sync_client.get_records(collection_name, full=True,
                                      headers=headers, **params)

    statsd_count(request, "syncclient.status_code.200")

    for r in records:
        r['last_modified'] = int(r.pop('modified') * 1000)

    # Configure headers
    export_headers(sync_client.raw_resp, request)

    if '_limit' in request.GET and 'Total-Records' in request.response.headers:
        del request.response.headers['Total-Records']

    return {'data': records or []}
 def test_should_decrypt_credentials(self):
     self.request.headers = {
         AUTHORIZATION_HEADER: 'Browserid 1234',
         CLIENT_STATE_HEADER: '12345'
     }
     with mock.patch.object(self.request.registry.cache,
                            'get',
                            return_value=ENCRYPTED_CREDENTIALS):
         with mock.patch('requests.request'):
             with mock.patch('syncto.authentication.decrypt',
                             return_value=json.dumps(self.credentials)) \
                     as mocked_decrypt:
                 build_sync_client(self.request)
                 mocked_decrypt.assert_called_with(ENCRYPTED_CREDENTIALS,
                                                   '12345',
                                                   'This is not a secret')
 def test_should_return_the_client_if_everything_is_fine(self):
     self.request.headers = {
         AUTHORIZATION_HEADER: 'Browserid 1234',
         CLIENT_STATE_HEADER: '12345'
     }
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.SyncClient') as SyncClient:
             build_sync_client(self.request)
             TSClient.assert_called_with(
                 '1234',
                 '12345',
                 'https://token.services.mozilla.com/',
                 verify=None)
             SyncClient.assert_called_with(verify=None, **self.credentials)
예제 #13
0
파일: record.py 프로젝트: greeshmab/syncto
def record_put(request):
    collection_name = request.matchdict['collection_name']

    assert_endpoint_enabled(request, collection_name)

    record_id = request.matchdict['record_id']
    sync_id = record_id

    headers = import_headers(request)
    record = request.validated['data']
    record['id'] = sync_id

    # Remove read-only fields
    record.pop('last_modified', None)

    sync_client = build_sync_client(request)
    last_modified = sync_client.put_record(collection_name, record,
                                           headers=headers)
    record['last_modified'] = int(last_modified * 1000)
    record['id'] = record_id

    # Configure headers
    export_headers(sync_client.raw_resp, request)

    status_code(request,str="syncclient.status_code.200")

    return {'data': record}
def record_put(request):
    collection_name = request.matchdict['collection_name']

    assert_endpoint_enabled(request, collection_name)

    record_id = request.matchdict['record_id']
    sync_id = record_id

    headers = import_headers(request)
    record = request.validated['data']
    record['id'] = sync_id

    # Remove read-only fields
    record.pop('last_modified', None)

    sync_client = build_sync_client(request)
    last_modified = sync_client.put_record(collection_name,
                                           record,
                                           headers=headers)
    record['last_modified'] = int(last_modified * 1000)
    record['id'] = record_id

    # Configure headers
    export_headers(sync_client.raw_resp, request)

    statsd_count(request, "syncclient.status_code.200")

    return {'data': record}
예제 #15
0
 def test_credentials_should_be_cached_encrypted(self):
     self.request.headers = {AUTHORIZATION_HEADER: 'Browserid 1234',
                             CLIENT_STATE_HEADER: '12345'}
     self.request.registry.cache.flush()
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.encrypt',
                         return_value='encrypted'):
             with mock.patch.object(self.request.registry.cache, 'set') \
                     as mocked_set:
                 build_sync_client(self.request)
                 cache_key = ('credentials_636130e072155efd00d8e27196500'
                              'd29110fb2e8e93bcedb2a30e0aa0e5ccf61')
                 mocked_set.assert_called_with(cache_key,
                                               'encrypted', 300)
예제 #16
0
 def test_should_handle_the_certificate_ca_parameters(self):
     digicert_ca_bundle = '../certificates/DigiCert.Global-Root-CA.crt'
     self.request.registry.settings.update({
         'certificate_ca_bundle': digicert_ca_bundle,
     })
     self.request.headers = {AUTHORIZATION_HEADER: 'Browserid 1234',
                             CLIENT_STATE_HEADER: '12345'}
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.SyncClient') as SyncClient:
             build_sync_client(self.request)
             TSClient.assert_called_once_with(
                 '1234', '12345', 'https://token.services.mozilla.com/',
                 verify=digicert_ca_bundle)
             SyncClient.assert_called_once_with(verify=digicert_ca_bundle,
                                                **self.credentials)
 def test_credentials_should_be_cached_encrypted(self):
     self.request.headers = {
         AUTHORIZATION_HEADER: 'Browserid 1234',
         CLIENT_STATE_HEADER: '12345'
     }
     self.request.registry.cache.flush()
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.encrypt',
                         return_value='encrypted'):
             with mock.patch.object(self.request.registry.cache, 'set') \
                     as mocked_set:
                 build_sync_client(self.request)
                 cache_key = ('credentials_636130e072155efd00d8e27196500'
                              'd29110fb2e8e93bcedb2a30e0aa0e5ccf61')
                 mocked_set.assert_called_with(cache_key, 'encrypted', 300)
예제 #18
0
 def test_should_cache_credentials_the_second_time(self):
     self.request.headers = {AUTHORIZATION_HEADER: 'Browserid 1234',
                             CLIENT_STATE_HEADER: '12345'}
     self.request.registry.cache.flush()
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.SyncClient') as SyncClient:
             # First call
             build_sync_client(self.request)
             SyncClient.assert_called_with(**self.credentials)
             # Second time
             build_sync_client(self.request)
             # TokenServerClient should have been called only once.
             TSClient.assert_called_once_with(
                 '1234', '12345', 'https://token.services.mozilla.com/')
             SyncClient.assert_called_with(**self.credentials)
 def test_statsd_time_sync_client_calls(self):
     with mock.patch.object(
             self.request.registry.cache, 'get',
             return_value=ENCRYPTED_CREDENTIALS.encode('utf-8')):
         with mock.patch('requests.request'):
             build_sync_client(self.request)
             self.mocked_client.timer.assert_any_call(
                 'syncclient.start_time')
             self.mocked_client.timer.assert_any_call(
                 'syncclient.syncclient.auth')
             self.mocked_client.timer.assert_any_call(
                 'syncclient.syncclient.get_records')
             self.mocked_client.timer.assert_any_call(
                 'syncclient.syncclient.get_record')
             self.mocked_client.timer.assert_any_call(
                 'syncclient.syncclient.put_record')
             self.mocked_client.timer.assert_any_call(
                 'syncclient.syncclient.delete_record')
 def test_should_return_an_alert_if_client_state_header_is_used(self):
     self.request.headers = {
         AUTHORIZATION_HEADER: 'Browserid 1234',
         CLIENT_STATE_HEADER: '12345'
     }
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.SyncClient'):
             build_sync_client(self.request)
             self.assertIn('Alert', self.request.response.headers)
             self.assertDictEqual(
                 json.loads(self.request.response.headers['Alert']), {
                     "url": "https://syncto.readthedocs.io/",
                     "message": "X-Client-State header is deprecated "
                     "and should not be provided anymore.",
                     "code": "soft-eol"
                 })
예제 #21
0
def collection_get(request):
    collection_name = request.matchdict["collection_name"]
    sync_client = build_sync_client(request)

    headers = import_headers(request)

    params = {}
    if "_since" in request.GET:
        try:
            params["newer"] = "%.2f" % (int(request.GET["_since"]) / 1000.0)
        except ValueError:
            error_msg = "_since should be a number."
            raise_invalid(request, location="querystring", name="_since", description=error_msg)

    if "_limit" in request.GET:
        params["limit"] = request.GET["_limit"]

    if "_token" in request.GET:
        params["offset"] = request.GET["_token"]

    if "_sort" in request.GET:
        if request.GET["_sort"] in ("-last_modified", "newest"):
            params["sort"] = "newest"

        elif request.GET["_sort"] in ("-sortindex", "index"):
            params["sort"] = "index"

        elif request.GET["_sort"] in ("last_modified", "oldest"):
            params["sort"] = "oldest"

        else:
            error_msg = (
                "_sort should be one of ('-last_modified', 'newest', "
                "'-sortindex', 'index', 'last_modified', 'oldest')"
            )
            raise_invalid(request, location="querystring", name="_sort", description=error_msg)

    if "in_ids" in request.GET:
        params["ids"] = [record_id.strip() for record_id in request.GET["in_ids"].split(",") if record_id]

    records = sync_client.get_records(collection_name, full=True, headers=headers, **params)

    status_code(request, str="syncclient.status_code.200")

    for r in records:
        r["last_modified"] = int(r.pop("modified") * 1000)

    # Configure headers
    export_headers(sync_client.raw_resp, request)

    if "_limit" in request.GET and "Total-Records" in request.response.headers:
        del request.response.headers["Total-Records"]

    if records:
        return {"data": records}
예제 #22
0
파일: record.py 프로젝트: Natim/syncto
def record_delete(request):
    collection_name = request.matchdict['collection_name']
    record_id = request.matchdict['record_id']
    sync_id = uuid4_to_base64(record_id)

    sync_client = build_sync_client(request)
    sync_client.delete_record(collection_name, sync_id)

    request.response.status_code = 204
    del request.response.headers['Content-Type']
    return request.response
 def test_should_handle_the_certificate_ca_parameters(self):
     digicert_ca_bundle = '../certificates/DigiCert.Global-Root-CA.crt'
     self.request.registry.settings.update({
         'certificate_ca_bundle':
         digicert_ca_bundle,
     })
     self.request.headers = {
         AUTHORIZATION_HEADER: 'Browserid 1234',
         CLIENT_STATE_HEADER: '12345'
     }
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.SyncClient') as SyncClient:
             build_sync_client(self.request)
             TSClient.assert_called_once_with(
                 '1234',
                 '12345',
                 'https://token.services.mozilla.com/',
                 verify=digicert_ca_bundle)
             SyncClient.assert_called_once_with(verify=digicert_ca_bundle,
                                                **self.credentials)
 def test_should_cache_credentials_the_second_time(self):
     self.request.headers = {
         AUTHORIZATION_HEADER: 'Browserid 1234',
         CLIENT_STATE_HEADER: '12345'
     }
     self.request.registry.cache.flush()
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.SyncClient') as SyncClient:
             # First call
             build_sync_client(self.request)
             SyncClient.assert_called_with(verify=None, **self.credentials)
             # Second time
             build_sync_client(self.request)
             # TokenServerClient should have been called only once.
             TSClient.assert_called_once_with(
                 '1234',
                 '12345',
                 'https://token.services.mozilla.com/',
                 verify=None)
             SyncClient.assert_called_with(verify=None, **self.credentials)
예제 #25
0
파일: collection.py 프로젝트: Natim/syncto
def collection_get(request):
    collection_name = request.matchdict['collection_name']
    sync_client = build_sync_client(request)

    params = {}
    if '_since' in request.GET:
        params['newer'] = request.GET['_since']

    if '_limit' in request.GET:
        params['limit'] = request.GET['_limit']

    if '_token' in request.GET:
        params['offset'] = request.GET['_token']

    if '_sort' in request.GET:
        if request.GET['_sort'] in ('-last_modified', 'newest'):
            params['sort'] = 'newest'

        elif request.GET['_sort'] in ('-sortindex', 'index'):
            params['sort'] = 'index'

        else:
            error_msg = ("_sort should be one of ('-last_modified', 'newest', "
                         "'-sortindex', 'index')")
            raise_invalid(request,
                          location="querystring",
                          name="_sort",
                          description=error_msg)

    if 'ids' in request.GET:
        try:
            params['ids'] = [uuid4_to_base64(record_id.strip())
                             for record_id in request.GET['ids'].split(',')
                             if record_id]
        except ValueError:
            raise_invalid(request,
                          location="querystring",
                          name="ids",
                          description="Invalid id in ids list.")

    records = sync_client.get_records(collection_name, full=True, **params)

    for r in records:
        r['last_modified'] = int(r.pop('modified') * 1000)
        r['id'] = base64_to_uuid4(r.pop('id'))

    # Configure headers
    convert_headers(sync_client.raw_resp, request.response)

    return {'data': records}
 def test_uses_ttl_from_settings_if_assertion_is_in_old_format(self):
     # This assertion comes from PyBrowserID tests cases.
     # https://github.com/mozilla/PyBrowserID
     assertion = """
     eyJjZXJ0aWZpY2F0ZXMiOlsiZXlKaGJHY2lPaUpTVXpFeU9DSjkuZXlKcGMzTWlPaUppY
     205M2MyVnlhV1F1YjNKbklpd2laWGh3SWpveE16SXhPVFF4T1Rnek1EVXdMQ0p3ZFdKc2
     FXTXRhMlY1SWpwN0ltRnNaMjl5YVhSb2JTSTZJbEpUSWl3aWJpSTZJamd4TmpreE5UQTB
     OVGswTkRVek5EVTFPREF4TlRreU5Ea3hNemsyTkRFNE56RTJNVFUwTkRNNE5EWXdPREl6
     TXpBMU1USXlPRGN3TURRNE56TTFNREk1TURrek16a3lNRFkzTURFMU1qQTBORGd6TWpVM
     U56WXdOREE1TnpFeU9EYzNNVGswT1RVek1UQXdNVFEyTkRVek56TTJOakU0TlRVek5EY3
     hNakkxT0RreU16TTFPRFV4TWpZNU1EQXdOREF5TVRrMk9ERTBNRGtpTENKbElqb2lOalU
     xTXpjaWZTd2ljSEpwYm1OcGNHRnNJanA3SW1WdFlXbHNJam9pY25saGJrQnlabXN1YVdR
     dVlYVWlmWDAua19oaEtYMFRCVnUyX2szbV9uRDVOVWJfTktwX19PLTY1MW1CRUl3S1NZZ
     GlOenQwQm9WRkNEVEVueEhQTWJCVjJaejk0WDgtLVRjVXJidEV0MWV1S1dWdjMtNTFUOU
     xBZnV6SEhfekNCUXJVbmxkMVpXSmpBM185ZEhQeTMwZzRMSU9YZTJWWmd0T1Nva3MyZFE
     4ZDNvazlSUTJQME5ERzB1MDBnN3lGejE4Il0sImFzc2VydGlvbiI6ImV5SmhiR2NpT2lK
     U1V6WTBJbjAuZXlKbGVIQWlPakV6TWpFNU1qazBOelU0TWprc0ltRjFaQ0k2SW1oMGRIQ
     TZMeTl0ZVdaaGRtOXlhWFJsWW1WbGNpNXZjbWNpZlEuQWhnS2Q0eXM0S3FnSGJYcUNSS3
     hHdlluVmFJOUwtb2hYSHk0SVBVWDltXzI0TWdfYlU2aGRIMTNTNnFnQy1vSHBpS3BfTGl
     6cDRGRjlUclBjNjBTRXcifQ
     """.replace(" ", "").replace("\n", "").strip()
     self.request.headers = {
         AUTHORIZATION_HEADER: 'Browserid ' + assertion,
         CLIENT_STATE_HEADER: '12345'
     }
     self.request.registry.cache.flush()
     with mock.patch('syncto.authentication.TokenserverClient') as TSClient:
         TSClient.return_value.get_hawk_credentials.return_value = \
             self.credentials
         with mock.patch('syncto.authentication.encrypt',
                         return_value='encrypted'):
             with mock.patch.object(self.request.registry.cache, 'set') \
                     as mocked_set:
                 build_sync_client(self.request)
                 args, _ = tuple(mocked_set.call_args_list[-1])
                 ttl = args[-1]
                 self.assertEqual(int(ttl), 300)
예제 #27
0
파일: record.py 프로젝트: Natim/syncto
def record_get(request):
    collection_name = request.matchdict['collection_name']
    record_id = request.matchdict['record_id']
    sync_id = uuid4_to_base64(record_id)

    sync_client = build_sync_client(request)
    record = sync_client.get_record(collection_name, sync_id)

    record['last_modified'] = int(record.pop('modified') * 1000)
    record['id'] = base64_to_uuid4(record.pop('id'))

    # Configure headers
    convert_headers(sync_client.raw_resp, request.response)

    return {'data': record}
def record_delete(request):
    collection_name = request.matchdict['collection_name']

    assert_endpoint_enabled(request, collection_name)

    record_id = request.matchdict['record_id']
    sync_id = record_id

    headers = import_headers(request)
    sync_client = build_sync_client(request)
    sync_client.delete_record(collection_name, sync_id, headers=headers)

    statsd_count(request, "syncclient.status_code.204")

    request.response.status_code = 204
    del request.response.headers['Content-Type']
    return request.response
예제 #29
0
파일: record.py 프로젝트: greeshmab/syncto
def record_get(request):
    collection_name = request.matchdict['collection_name']
    record_id = request.matchdict['record_id']

    sync_client = build_sync_client(request)
    headers = import_headers(request)
    record = sync_client.get_record(collection_name, record_id,
                                    headers=headers)

    record['last_modified'] = int(record.pop('modified') * 1000)

    # Configure headers
    export_headers(sync_client.raw_resp, request)

    status_code(request,str="syncclient.status_code.200")

    return {'data': record}
예제 #30
0
파일: record.py 프로젝트: greeshmab/syncto
def record_delete(request):
    collection_name = request.matchdict['collection_name']

    assert_endpoint_enabled(request, collection_name)

    record_id = request.matchdict['record_id']
    sync_id = record_id

    headers = import_headers(request)
    sync_client = build_sync_client(request)
    sync_client.delete_record(collection_name, sync_id, headers=headers)

    status_code(request,str="syncclient.status_code.204")

    request.response.status_code = 204
    del request.response.headers['Content-Type']
    return request.response
def record_get(request):
    collection_name = request.matchdict['collection_name']
    record_id = request.matchdict['record_id']

    sync_client = build_sync_client(request)
    headers = import_headers(request)
    record = sync_client.get_record(collection_name,
                                    record_id,
                                    headers=headers)

    record['last_modified'] = int(record.pop('modified') * 1000)

    # Configure headers
    export_headers(sync_client.raw_resp, request)

    statsd_count(request, "syncclient.status_code.200")

    return {'data': record}
예제 #32
0
파일: record.py 프로젝트: Natim/syncto
def record_put(request):
    collection_name = request.matchdict['collection_name']
    record_id = request.matchdict['record_id']
    sync_id = uuid4_to_base64(record_id)

    if_unmodified_since = request.headers.get('If-Match')

    record = request.validated['data']
    record['id'] = sync_id

    sync_client = build_sync_client(request)
    last_modified = sync_client.put_record(collection_name, record,
                                           if_unmodified_since)
    record['last_modified'] = int(last_modified * 1000)
    record['id'] = record_id

    # Configure headers
    convert_headers(sync_client.raw_resp, request.response)

    return {'data': record}
예제 #33
0
def collection_get(request):
    collection_name = request.matchdict['collection_name']
    sync_client = build_sync_client(request)

    headers = import_headers(request)

    params = {}
    if '_since' in request.GET:
        try:
            params['newer'] = '%.2f' % (int(request.GET['_since']) / 1000.0)
        except ValueError:
            error_msg = ("_since should be a number.")
            raise_invalid(request,
                          location="querystring",
                          name="_since",
                          description=error_msg)

    if '_limit' in request.GET:
        params['limit'] = request.GET['_limit']

    if '_token' in request.GET:
        params['offset'] = request.GET['_token']

    if '_sort' in request.GET:
        if request.GET['_sort'] in ('-last_modified', 'newest'):
            params['sort'] = 'newest'

        elif request.GET['_sort'] in ('-sortindex', 'index'):
            params['sort'] = 'index'

        elif request.GET['_sort'] in ('last_modified', 'oldest'):
            params['sort'] = 'oldest'

        else:
            error_msg = ("_sort should be one of ('-last_modified', 'newest', "
                         "'-sortindex', 'index', 'last_modified', 'oldest')")
            raise_invalid(request,
                          location="querystring",
                          name="_sort",
                          description=error_msg)

    if 'in_ids' in request.GET:
        params['ids'] = [
            record_id.strip() for record_id in request.GET['in_ids'].split(',')
            if record_id
        ]

    records = sync_client.get_records(collection_name,
                                      full=True,
                                      headers=headers,
                                      **params)

    statsd_count(request, "syncclient.status_code.200")

    for r in records:
        r['last_modified'] = int(r.pop('modified') * 1000)

    # Configure headers
    export_headers(sync_client.raw_resp, request)

    if '_limit' in request.GET and 'Total-Records' in request.response.headers:
        del request.response.headers['Total-Records']

    return {'data': records or []}
예제 #34
0
 def test_should_return_the_client_if_everything_is_fine(self):
     self.request.headers = {AUTHORIZATION_HEADER: 'Browserid 1234',
                             CLIENT_STATE_HEADER: '12345'}
     with mock.patch('syncto.authentication.SyncClient') as SyncClient:
         build_sync_client(self.request)
         SyncClient.assert_called_with('1234', '12345')