예제 #1
0
    def test_webhook_ulb_pull_request(self, mock_reporter, mock_url_exists):
        request_file = os.path.join(self.resources_dir,
                                    'ulb-pull-request.json')
        with codecs.open(request_file, 'r', encoding='utf-8') as in_file:
            request_text = in_file.read()
            # convert Windows line endings to Linux line endings
            content = request_text.replace('\r\n', '\n')

            # deserialized object
            request_json = json.loads(content)

        mockLogger = MockLogger()
        mockDCS = MockAPI(self.resources_dir, 'https://git.door43.org/')
        urls = {
            'https://git.door43.org/Door43-Catalog/en_ulb/archive/2fbfd081f46487e48e49090a95c48d45e04e6bed.zip':
            'en_ulb.zip'
        }
        mock_download = lambda url, dest: mockDCS.download_file(
            urls[url], dest)
        self.MockDynamodbHandler.data = None
        self.MockS3Handler.reset()
        handler = WebhookHandler(event=request_json,
                                 context=None,
                                 logger=mockLogger,
                                 s3_handler=self.MockS3Handler,
                                 dynamodb_handler=self.MockDynamodbHandler,
                                 download_handler=mock_download)

        with self.assertRaises(Exception) as error_context:
            handler.run()
        self.assertIn('Skipping un-merged pull request',
                      str(error_context.exception))
        entry = self.MockDynamodbHandler.data
        self.assertEqual(0, len(self.MockS3Handler.uploads))
        self.assertIsNone(entry)
예제 #2
0
    def test_webhook_with_missing_obs_data(self, mock_reporter,
                                           mock_url_exists):
        request_file = os.path.join(self.resources_dir,
                                    'obs-missing-request.json')

        with codecs.open(request_file, 'r', encoding='utf-8') as in_file:
            request_text = in_file.read()
            # convert Windows line endings to Linux line endings
            content = request_text.replace('\r\n', '\n')

            # deserialized object
            request_json = json.loads(content)

        mockLogger = MockLogger()
        mockDCS = MockAPI(self.resources_dir, 'https://git.door43.org/')
        self.MockDynamodbHandler.data = None
        self.MockS3Handler.reset()
        urls = {
            'https://git.door43.org/Door43-Catalog/ylb_obs/archive/f8a8d8d757e7ea287cf91b266963f8523bdbd5ad.zip':
            'ylb_obs_missing_data.zip'
        }
        mock_download = lambda url, dest: mockDCS.download_file(
            urls[url], dest)
        handler = WebhookHandler(event=request_json,
                                 context=None,
                                 logger=mockLogger,
                                 s3_handler=self.MockS3Handler,
                                 dynamodb_handler=self.MockDynamodbHandler,
                                 download_handler=mock_download)
        handler.run()

        entry = self.MockDynamodbHandler.data
        self.assertEqual(1, len(self.MockS3Handler.uploads))
        self.assertIn('/ylb_obs.zip', self.MockS3Handler.uploads[0]['path'])
        self.assertIn(
            'temp/ylb_obs/{}/ylb/obs/v4.1/obs.zip'.format(entry['commit_id']),
            self.MockS3Handler.uploads[0]['key'])

        self.assertEqual('f8a8d8d757', entry['commit_id'])
        self.assertEqual(False, entry['dirty'])
        self.assertEqual('ylb', entry['language'])
        self.assertEqual('2017-04-25T21:46:30+00:00', entry['timestamp'])
        self.assertEqual(False, entry['signed'])
        self.assertEqual('ylb_obs', entry['repo_name'])
        assert_object_equals_file(
            self, json.loads(entry['package']),
            os.path.join(self.resources_dir,
                         'expected_obs_package_missing_data.json'))
예제 #3
0
    def test_signing_handler_already_signed(self, mock_reporter):
        event = self.create_event()
        mock_s3 = MockS3Handler()
        mock_db = MockDynamodbHandler()
        mock_db._load_db(
            os.path.join(self.resources_dir, 'db/valid_signed.json'))
        mock_logger = MockLogger()
        original_record = mock_db.get_item({'repo_name': 'en_obs'}).copy()
        self.assertFalse(original_record['signed'])

        mock_api = MockAPI(os.path.join(self.resources_dir, 'cdn'),
                           'https://cdn.door43.org')

        signer = SigningHandler(event,
                                None,
                                logger=mock_logger,
                                signer=self.mock_signer,
                                s3_handler=mock_s3,
                                dynamodb_handler=mock_db,
                                url_exists_handler=mock_api.url_exists,
                                download_handler=mock_api.download_file)

        result = signer.run()
        self.assertTrue(result)

        updated_record = mock_db.get_item({'repo_name': 'en_obs'}).copy()
        self.assertTrue(updated_record['signed'])
예제 #4
0
    def test_signing_handler_text_wrong_key(self, mock_reporter):
        event = self.create_event()

        mock_db = MockDynamodbHandler()
        mock_db._load_db(
            os.path.join(self.resources_dir, 'db/valid_unsigned.json'))

        mock_s3 = MockS3Handler()
        mock_s3._load_path(os.path.join(self.resources_dir, 'cdn'))

        mock_api = MockAPI(os.path.join(self.resources_dir, 'cdn'),
                           'https://cdn.door43.org')

        mock_logger = MockLogger()

        # TRICKY: a wrong signing key will result in failed verification
        self.mock_signer._fail_verification()
        signer = SigningHandler(event,
                                None,
                                logger=mock_logger,
                                signer=self.mock_signer,
                                s3_handler=mock_s3,
                                dynamodb_handler=mock_db,
                                url_exists_handler=mock_api.url_exists,
                                download_handler=mock_api.download_file)
        result = signer.run()

        self.assertTrue(result)
        for f in mock_s3._recent_uploads:
            # assert nothing was uploaded to production
            self.assertTrue(f.startswith('temp/'))
            self.assertFalse(f.endswith('.sig'))
        self.assertIn('The signature was not successfully verified.',
                      mock_logger._messages)
    def test_skip_signing_large_file(self, mock_reporter):
        """
        Ensure that large files are not signed.
        Because lambda functions have limited disk space.
        :return:
        """
        mock_instance = MagicMock()
        mock_instance.add_error = MagicMock()
        mock_reporter.return_value = mock_instance

        mock_s3 = MockS3Handler()
        mock_db = MockDynamodbHandler()
        mock_logger = MockLogger()
        mock_logger.warning = MagicMock()
        mock_api = MockAPI(os.path.join(self.resources_dir, 'cdn'),
                           'https://cdn.door43.org/')
        event = self.create_event()
        item = {'repo_name': 'repo_name', 'commit_id': 'commitid'}
        format = {
            "build_rules": ["signing.sign_given_url"],
            "chapters": [],
            "contributor": [
                "Narrator: Steve Lossing", "Checker: Brad Harrington",
                "Engineer: Brad Harrington"
            ],
            "format":
            "",
            "modified":
            "",
            "quality":
            "64kbps",
            "signature":
            "",
            "size":
            0,
            "url":
            "https://cdn.door43.org/en/obs/v4/64kbps/en_obs_64kbps.zip"
        }
        mockHeaders = HeaderReader([('content-length',
                                     SigningHandler.max_file_size + 1)])

        signer = SigningHandler(event=event,
                                context=None,
                                logger=mock_logger,
                                signer=self.mock_signer,
                                s3_handler=mock_s3,
                                dynamodb_handler=mock_db,
                                url_exists_handler=mock_api.url_exists,
                                download_handler=mock_api.download_file,
                                url_headers_handler=lambda url: mockHeaders)
        (already_signed,
         newly_signed) = signer.process_format(item, None, None, format)
        mock_logger.warning.assert_called_once_with(
            'File is too large to sign https://cdn.door43.org/en/obs/v4/64kbps/en_obs_64kbps.zip'
        )
        self.assertTrue(already_signed)
        self.assertEqual(
            'https://cdn.door43.org/en/obs/v4/64kbps/en_obs_64kbps.zip.sig',
            format['signature'])
        self.assertTrue(newly_signed)
예제 #6
0
    def test_webhook_ulb(self, mock_reporter, mock_url_exists):
        request_file = os.path.join(self.resources_dir, 'ulb-request.json')

        with codecs.open(request_file, 'r', encoding='utf-8') as in_file:
            request_text = in_file.read()
            # convert Windows line endings to Linux line endings
            content = request_text.replace('\r\n', '\n')

            # deserialized object
            request_json = json.loads(content)

        mockLogger = MockLogger()
        mockDCS = MockAPI(self.resources_dir, 'https://git.door43.org/')
        urls = {
            'https://git.door43.org/Door43-Catalog/en_ulb/archive/2fbfd081f46487e48e49090a95c48d45e04e6bed.zip':
            'en_ulb.zip'
        }
        mock_download = lambda url, dest: mockDCS.download_file(
            urls[url], dest)
        self.MockDynamodbHandler.data = None
        self.MockS3Handler.reset()
        handler = WebhookHandler(event=request_json,
                                 context=None,
                                 logger=mockLogger,
                                 s3_handler=self.MockS3Handler,
                                 dynamodb_handler=self.MockDynamodbHandler,
                                 download_handler=mock_download)
        handler.run()

        entry = self.MockDynamodbHandler.data
        self.assertEqual(4,
                         len(self.MockS3Handler.uploads))  # books and bundle
        self.assertIn('/en_ulb.zip', self.MockS3Handler.uploads[0]['path'])

        self.assertEqual('2fbfd081f4', entry['commit_id'])
        self.assertEqual(False, entry['dirty'])
        self.assertEqual('en', entry['language'])
        self.assertEqual('2017-05-02T22:52:04+00:00', entry['timestamp'])
        self.assertEqual(False, entry['signed'])
        self.assertEqual('en_ulb', entry['repo_name'])
        self.assertIn(
            'temp/en_ulb/{}/en/ulb/v7/ulb.zip'.format(entry['commit_id']),
            self.MockS3Handler.uploads[0]['key'])

        assert_object_equals_file(
            self, json.loads(entry['package']),
            os.path.join(self.resources_dir, 'expected_ulb_package.json'))
예제 #7
0
    def test_webhook_ulb_merged_pull_request(self, mock_reporter,
                                             mock_url_exists):
        request_file = os.path.join(self.resources_dir,
                                    'ulb-merged-pull-request.json')
        with codecs.open(request_file, 'r', encoding='utf-8') as in_file:
            request_text = in_file.read()
            # convert Windows line endings to Linux line endings
            content = request_text.replace('\r\n', '\n')

            # deserialized object
            request_json = json.loads(content)

        mockLogger = MockLogger()
        mockDCS = MockAPI(self.resources_dir, 'https://git.door43.org/')
        urls = {
            'https://git.door43.org/Door43-Catalog/ta_ulb/archive/0a7e25cd939f00086262fe94b9d25afc3b5dabd3.zip':
            'ta_ulb.zip'
        }
        mock_download = lambda url, dest: mockDCS.download_file(
            urls[url], dest)
        self.MockDynamodbHandler.data = None
        self.MockS3Handler.reset()
        handler = WebhookHandler(event=request_json,
                                 context=None,
                                 logger=mockLogger,
                                 s3_handler=self.MockS3Handler,
                                 dynamodb_handler=self.MockDynamodbHandler,
                                 download_handler=mock_download)
        handler.run()
        entry = self.MockDynamodbHandler.data
        self.assertEqual(4,
                         len(self.MockS3Handler.uploads))  # books and bundle
        self.assertIn('/ta_ulb.zip', self.MockS3Handler.uploads[0]['path'])

        self.assertEqual('0a7e25cd93', entry['commit_id'])
        self.assertEqual(False, entry['dirty'])
        self.assertEqual('ta', entry['language'])
        self.assertEqual('2017-08-17T18:56:52.884140+00:00',
                         entry['timestamp'])
        self.assertEqual(False, entry['signed'])
        self.assertEqual('ta_ulb', entry['repo_name'])
        self.assertIn(
            'temp/ta_ulb/{}/ta/ulb/v3/ulb.zip'.format(entry['commit_id']),
            self.MockS3Handler.uploads[0]['key'])
예제 #8
0
    def test_signing_handler_s3(self, mock_reporter):
        mock_s3 = MockS3Handler()
        mock_s3._load_path(os.path.join(self.resources_dir, 'cdn'))

        mock_db = MockDynamodbHandler()
        mock_db._load_db(
            os.path.join(self.resources_dir, 'db/valid_unsigned.json'))

        mock_logger = MockLogger()

        mock_api = MockAPI(os.path.join(self.resources_dir, 'cdn'),
                           'https://cdn.door43.org/')

        event = self.create_event()

        original_item = mock_db.get_item({'repo_name': 'en_obs'}).copy()
        self.assertIn('signed', original_item)
        self.assertFalse(original_item['signed'])

        global_headers = HeaderReader([('last-modified',
                                        'Fri, 03 Jun 2017 20:23:12 GMT'),
                                       ('content-length', 12345)])

        signer = SigningHandler(event,
                                None,
                                logger=mock_logger,
                                signer=self.mock_signer,
                                s3_handler=mock_s3,
                                dynamodb_handler=mock_db,
                                url_exists_handler=mock_api.url_exists,
                                download_handler=mock_api.download_file,
                                url_headers_handler=lambda url: global_headers)
        result = signer.run()
        self.assertTrue(result)

        self.assertTrue(len(mock_s3._recent_uploads) > 0)
        has_prod_uploads = False
        for key in mock_s3._recent_uploads:
            # assert prod uploads have signatures
            if not key.startswith('temp/') and not key.endswith('.sig'):
                has_prod_uploads = True
                self.assertIn('{}.sig'.format(key), mock_s3._recent_uploads)
        self.assertTrue(has_prod_uploads)

        updated_item = mock_db.get_item({'repo_name': 'en_obs'}).copy()
        assert_object_not_equals(self, updated_item, original_item)
        assert_object_equals_file(
            self, json.loads(updated_item['package']),
            os.path.join(self.resources_dir,
                         'db/expected_signed_package.json'))

        self.assertIn(
            'Skipping chapter obs:01 missing url https://cdn.door43.org/en/obs/v4/32kbps/en_obs_01_32kbps.mp3',
            mock_logger._messages)
        self.assertTrue(updated_item['signed'])
예제 #9
0
    def test_create_v2_catalog(self, mock_reporter):
        mockDB = MockDynamodbHandler()
        mockDB._load_db(
            os.path.join(TestUwV2Catalog.resources_dir, 'ready_new_db.json'))
        mockV3Api = MockAPI(os.path.join(self.resources_dir, 'v3_api'),
                            'https://api.door43.org/')
        mockV3Api.add_host(os.path.join(self.resources_dir, 'v3_cdn'),
                           'https://cdn.door43.org/')
        mockV2Api = MockAPI(os.path.join(self.resources_dir, 'v2_api'),
                            'https://test')
        mockS3 = MockS3Handler('uw_bucket')
        mockSigner = MockSigner()
        mockLogger = MockLogger()

        converter = UwV2CatalogHandler(
            event=self._make_event(),
            context=None,
            logger=mockLogger,
            s3_handler=mockS3,
            dynamodb_handler=mockDB,
            url_handler=mockV3Api.get_url,
            download_handler=mockV3Api.download_file,
            signing_handler=mockSigner)
        converter.run()

        assert_s3_equals_api_json(self, mockS3, mockV2Api,
                                  'v2/uw/catalog.json')
        assert_s3_equals_api_json(self, mockS3, mockV2Api,
                                  'v2/uw/obs/en/obs/v4/source.json')
        assert_s3_equals_api_text(self, mockS3, mockV2Api,
                                  'v2/uw/gen/en/udb/v7/gen.usfm')
        assert_s3_equals_api_text(self, mockS3, mockV2Api,
                                  'v2/uw/1ch/en/ulb/v7/1ch.usfm')
        self.assertIn('v2/uw/obs/en/obs/v4/source.json.sig',
                      mockS3._recent_uploads)
        self.assertIn('uw/txt/2/catalog.json', mockS3._recent_uploads)
        self.assertIn(
            'en_udb_1ch: media format "https://cdn.door43.org/en/udb/v9/1ch.pdf" does not match source version "7" and will be excluded.',
            mockLogger._messages)
        self.assertIn(
            'en_obs_obs: media format "https://cdn.door43.org/en/obs/v999/129kbps/en_obs_129kbps.zip" does not match source version "4" and will be excluded.',
            mockLogger._messages)
예제 #10
0
    def make_handler_instance(self, progress_db):
        """
        Generates a new handler instance for testing
        :param progress_db:
        :return:
        """
        progress_db_file = os.path.join(self.resources_dir,
                                        'progress_db/{}'.format(progress_db))
        self.assertTrue(os.path.isfile(progress_db_file))

        # now run the code
        event = self.create_event()
        mock_progress_db = MockDynamodbHandler()
        mock_progress_db._load_db(progress_db_file)
        mock_status_db = MockDynamodbHandler()
        mock_errors_db = MockDynamodbHandler()
        dbs = {
            'd43-catalog-in-progress': mock_progress_db,
            'd43-catalog-status': mock_status_db,
            'd43-catalog-errors': mock_errors_db
        }

        mock_ses = MockSESHandler()
        mock_s3 = MockS3Handler()
        mock_checker = MockChecker()
        mock_api = MockAPI(os.path.join(self.resources_dir), '/')

        mock_ses_handler = lambda: mock_ses
        mock_s3_handler = lambda bucket: mock_s3
        mock_dbs_handler = lambda bucket: dbs[bucket]
        mock_checker_handler = lambda: mock_checker
        handler = CatalogHandler(event,
                                 None,
                                 s3_handler=mock_s3_handler,
                                 dynamodb_handler=mock_dbs_handler,
                                 ses_handler=mock_ses_handler,
                                 consistency_checker=mock_checker_handler,
                                 url_exists_handler=lambda url: True,
                                 get_url_handler=mock_api.get_url)
        return {
            'handler': handler,
            'event': event,
            'mocks': {
                'db': {
                    'progress': mock_progress_db,
                    'status': mock_status_db,
                    'errors': mock_errors_db
                },
                'api': mock_api,
                'ses': mock_ses,
                's3': mock_s3,
                'checker': mock_checker
            }
        }
예제 #11
0
    def test_broken_catalog(self, mock_reporter):
        mockV3Api = MockAPI(os.path.join(self.resources_dir, 'v3_cdn'),
                            'https://cdn.door43.org/')
        mockV3Api.add_host(os.path.join(self.resources_dir, 'broken_api'),
                           'https://api.door43.org/')
        mockS3 = MockS3Handler('ts_bucket')
        mockDb = MockDynamodbHandler()
        mockDb._load_db(
            os.path.join(TestTsV2Catalog.resources_dir, 'ready_new_db.json'))
        mockLog = MockLogger()
        mock_get_url = lambda url, catch_exception: mockV3Api.get_url(
            url, catch_exception)
        mock_download = lambda url, dest: mockV3Api.download_file(url, dest)

        event = self.make_event()
        converter = TsV2CatalogHandler(event=event,
                                       context=None,
                                       logger=mockLog,
                                       s3_handler=mockS3,
                                       dynamodb_handler=mockDb,
                                       url_handler=mock_get_url,
                                       download_handler=mock_download,
                                       url_exists_handler=lambda url: False)
        result = converter.run()
        self.assertFalse(result)
        self.assertIn(
            'Failed to load the catalog json: No JSON object could be decoded',
            mockLog._messages)
예제 #12
0
    def test_missing_catalog(self, mock_reporter):
        mockV3Api = MockAPI(self.resources_dir, 'https://api.door43.org/')
        mockV3Api.add_host(os.path.join(self.resources_dir, 'v3_cdn'),
                           'https://cdn.door43.org/')
        mockV3Api.add_host(os.path.join(self.resources_dir, 'v3_cdn'),
                           'https://test-cdn.door43.org/')

        mockS3 = MockS3Handler('ts_bucket')
        mockDb = MockDynamodbHandler()
        mockDb._load_db(
            os.path.join(TestTsV2Catalog.resources_dir, 'ready_new_db.json'))
        mockLog = MockLogger()

        event = self.make_event()
        converter = TsV2CatalogHandler(
            event=event,
            context=None,
            logger=mockLog,
            s3_handler=mockS3,
            dynamodb_handler=mockDb,
            url_handler=mockV3Api.get_url,
            download_handler=mockV3Api.download_file,
            url_exists_handler=lambda url: False)
        result = converter.run()
        self.assertFalse(result)
        self.assertIn('https://api.door43.org/v3/catalog.json does not exist',
                      mockLog._messages)
예제 #13
0
 def test_signing_small_file(self, mock_reporter):
     """
     Ensure that small files are signed properly
     :return:
     """
     mock_s3 = MockS3Handler()
     mock_db = MockDynamodbHandler()
     mock_logger = MockLogger()
     mock_api = MockAPI(os.path.join(self.resources_dir, 'cdn'),
                        'https://cdn.door43.org/')
     event = self.create_event()
     item = {'repo_name': 'repo_name', 'commit_id': 'commitid'}
     format = {
         "build_rules": ["signing.sign_given_url"],
         "chapters": [],
         "contributor": [
             "Narrator: Steve Lossing", "Checker: Brad Harrington",
             "Engineer: Brad Harrington"
         ],
         "format":
         "",
         "modified":
         "",
         "quality":
         "64kbps",
         "signature":
         "",
         "size":
         0,
         "url":
         "https://cdn.door43.org/en/obs/v4/64kbps/en_obs_64kbps.zip"
     }
     mockHeaders = HeaderReader([('content-length', 123)])
     signer = SigningHandler(event,
                             None,
                             logger=mock_logger,
                             signer=self.mock_signer,
                             s3_handler=mock_s3,
                             dynamodb_handler=mock_db,
                             url_exists_handler=mock_api.url_exists,
                             download_handler=mock_api.download_file,
                             url_headers_handler=lambda url: mockHeaders)
     (already_signed,
      newly_signed) = signer.process_format(item, None, None, format)
     self.assertEqual(
         'https://cdn.door43.org/en/obs/v4/64kbps/en_obs_64kbps.zip.sig',
         format['signature'])
     self.assertNotIn(
         'File is too large to sign https://cdn.door43.org/en/obs/v4/64kbps/en_obs_64kbps.zip',
         mock_logger._messages)
     self.assertFalse(already_signed)
     self.assertTrue(newly_signed)
예제 #14
0
    def test_complete_status(self, mock_reporter):
        mockV3Api = MockAPI(self.resources_dir, 'https://cdn.door43.org/')
        mockS3 = MockS3Handler('ts_bucket')
        mockDb = MockDynamodbHandler()
        mockDb._load_db(
            os.path.join(TestTsV2Catalog.resources_dir, 'complete_db.json'))
        mockLog = MockLogger()
        mock_get_url = lambda url, catch_exception: mockV3Api.get_url(
            url, catch_exception)
        mock_download = lambda url, dest: mockV3Api.download_file(url, dest)

        event = self.make_event()
        converter = TsV2CatalogHandler(event=event,
                                       context=None,
                                       logger=mockLog,
                                       s3_handler=mockS3,
                                       dynamodb_handler=mockDb,
                                       url_handler=mock_get_url,
                                       download_handler=mock_download,
                                       url_exists_handler=lambda url: True)
        result = converter.run()
        self.assertTrue(result)
        self.assertEqual(0, len(mockS3._recent_uploads))
        self.assertIn('Catalog already generated', mockLog._messages)
예제 #15
0
    def test_signing_handler_text_no_records(self, mock_reporter):
        event = self.create_event()
        mock_db = MockDynamodbHandler()
        mock_s3 = MockS3Handler()

        mock_api = MockAPI(os.path.join(self.resources_dir, 'cdn'),
                           'https://cdn.door43.org')

        handler = SigningHandler(event,
                                 None,
                                 logger=MockLogger(),
                                 signer=self.mock_signer,
                                 s3_handler=mock_s3,
                                 dynamodb_handler=mock_db,
                                 url_exists_handler=mock_api.url_exists,
                                 download_handler=mock_api.download_file)
        result = handler.run()
        self.assertFalse(result)
예제 #16
0
    def test_index_inconsistent_image_titles(self):
        mockApi = MockAPI(self.resources_dir, 'https://example.com')
        format = {
            'format': 'type=book',
            'url': 'https://example.com/en_obs.zip'
        }
        response = index_obs('en', 'obs', format, self.temp_dir,
                             mockApi.download_file)
        chapters = response['chapters']
        self.assertEqual(2, len(chapters))

        self.assertEqual('01', chapters[0]['number'])
        self.assertEqual(16, len(chapters[0]['frames']))
        frames = chapters[0]['frames']
        self.assertEqual('01-01', frames[0]['id'])
        self.assertEqual('01-02', frames[1]['id'])

        self.assertEqual('02', chapters[1]['number'])
        self.assertEqual(12, len(chapters[1]['frames']))
예제 #17
0
    def test_signing_handler_text_missing_file(self, mock_url_headers,
                                               mock_reporter):
        """
        Signing will continue to run even if a file is missing.
        The missing file will just be ignored.
        :return:
        """
        mock_url_headers.return_value = HeaderReader([
            ('last-modified', 'Fri, 03 Jun 2017 20:23:12 GMT'),
            ('content-length', 12345)
        ])

        mock_instance = MagicMock()
        mock_instance.add_error = MagicMock()
        mock_reporter.return_value = mock_instance

        event = self.create_event()

        mock_db = MockDynamodbHandler()
        mock_db._load_db(
            os.path.join(self.resources_dir, 'db/valid_unsigned.json'))

        mock_api = MockAPI(os.path.join(self.resources_dir, 'cdn'),
                           'https://cdn.door43.org')

        mock_logger = MockLogger()
        mock_s3 = MockS3Handler()

        signer = SigningHandler(event,
                                None,
                                logger=mock_logger,
                                signer=self.mock_signer,
                                s3_handler=mock_s3,
                                dynamodb_handler=mock_db,
                                url_exists_handler=mock_api.url_exists,
                                download_handler=mock_api.download_file)
        result = signer.run()
        self.assertTrue(result)
        mock_instance.add_error.assert_called_once_with(
            'The file "obs.zip" could not be downloaded: File not found for key: temp/en_obs/f8a8d8d757/en/obs/v4/obs.zip'
        )
 def test_signing_remote_3gp_file(self, mock_reporter):
     """
     Ensure that small files are signed properly
     :return:
     """
     mock_s3 = MockS3Handler()
     mock_db = MockDynamodbHandler()
     mock_logger = MockLogger()
     mock_api = MockAPI(os.path.join(self.resources_dir, 'filedn'),
                        'https://filedn.com/')
     event = self.create_event()
     item = {'repo_name': 'repo_name', 'commit_id': 'commitid'}
     format = {
         "build_rules": ["signing.sign_given_url"],
         "chapters": [],
         "contributor": [],
         "format": "",
         "modified": "",
         "quality": "3GP",
         "signature": "",
         "size": 0,
         "url": "https://filedn.com/XYZ/en/obs/v6/en_obs_v6_3GP.zip"
     }
     mockHeaders = HeaderReader([('content-length', 345)])
     signer = SigningHandler(event,
                             None,
                             logger=mock_logger,
                             signer=self.mock_signer,
                             s3_handler=mock_s3,
                             dynamodb_handler=mock_db,
                             url_exists_handler=mock_api.url_exists,
                             download_handler=mock_api.download_file,
                             url_headers_handler=lambda url: mockHeaders)
     (already_signed,
      newly_signed) = signer.process_format(item, None, None, format)
     self.assertEqual('', format['signature'])
     self.assertEqual('application/zip; content=video/3gpp',
                      format['format'])
     self.assertEqual(116, format['size'])
     self.assertTrue(already_signed)
     self.assertTrue(newly_signed)
예제 #19
0
    def test_status_not_ready(self, mock_reporter):
        mockDB = MockDynamodbHandler()
        mockDB._load_db(
            os.path.join(TestUwV2Catalog.resources_dir, 'not_ready_db.json'))
        mockV3Api = MockAPI(os.path.join(self.resources_dir, 'v3_api'),
                            'https://api.door43.org/')
        mockS3 = MockS3Handler('uw_bucket')
        mockSigner = MockSigner()
        mockLogger = MockLogger()

        converter = UwV2CatalogHandler(
            event=self._make_event(),
            context=None,
            logger=mockLogger,
            s3_handler=mockS3,
            dynamodb_handler=mockDB,
            url_handler=mockV3Api.get_url,
            download_handler=mockV3Api.download_file,
            signing_handler=mockSigner)
        result = converter._get_status()
        self.assertFalse(result)
예제 #20
0
    def test_signing_obs_html(self, mock_reporter):
        mock_s3 = MockS3Handler()
        mock_db = MockDynamodbHandler()
        mock_logger = MockLogger()
        mock_api = MockAPI(os.path.join(self.resources_dir, 'cdn'),
                           'https://cdn.door43.org/')
        event = self.create_event()
        item = {'repo_name': 'repo_name', 'commit_id': 'commitid'}
        format = {
            "build_rules": ["signing.html_format"],
            "format": "text/html",
            "modified": "",
            "signature": "",
            "size": "",
            # NOTE: this is not the actual url format used
            "url": "https://cdn.door43.org/temp/en_obs/f8a8d8d757/en/obs.html"
        }

        dublin_core = {"identifier": "obs", "language": {"identifier": "en"}}
        mockHeaders = HeaderReader([('content-length', 123)])
        signer = SigningHandler(event,
                                None,
                                logger=mock_logger,
                                signer=self.mock_signer,
                                s3_handler=mock_s3,
                                dynamodb_handler=mock_db,
                                url_exists_handler=mock_api.url_exists,
                                download_handler=mock_api.download_file,
                                url_headers_handler=lambda url: mockHeaders)
        (already_signed,
         newly_signed) = signer.process_format(item, dublin_core, None, format)
        self.assertEqual(
            'https://cdn.door43.org/en/obs/v3/media/html/obs.html',
            format['url'])
        self.assertEqual(
            'https://cdn.door43.org/en/obs/v3/media/html/obs.html.sig',
            format['signature'])
        self.assertFalse(already_signed)
        self.assertTrue(newly_signed)
예제 #21
0
    def test_status_ready_new_db(self, mock_reporter):
        mockDB = MockDynamodbHandler()
        mockDB._load_db(
            os.path.join(TestUwV2Catalog.resources_dir, 'ready_new_db.json'))
        mockV3Api = MockAPI(os.path.join(self.resources_dir, 'v3_api'),
                            'https://api.door43.org/')
        mockS3 = MockS3Handler('uw_bucket')
        mockSigner = MockSigner()
        mockLogger = MockLogger()

        converter = UwV2CatalogHandler(
            event=self._make_event(),
            context=None,
            logger=mockLogger,
            s3_handler=mockS3,
            dynamodb_handler=mockDB,
            url_handler=mockV3Api.get_url,
            download_handler=mockV3Api.download_file,
            signing_handler=mockSigner)
        (status, source_status) = converter._get_status()
        self.assertEqual('complete', source_status['state'])
        self.assertEqual('in-progress', status['state'])
        self.assertEqual(0, len(status['processed']))
예제 #22
0
    def test_malformed_manifest(self, mock_reporter, mock_url_exists):
        mock_instance = MagicMock()
        mock_instance.add_error = MagicMock()
        mock_reporter.return_value = mock_instance

        request_file = os.path.join(self.resources_dir,
                                    'malformed-manifest.json')

        with codecs.open(request_file, 'r', encoding='utf-8') as in_file:
            request_text = in_file.read()
            # convert Windows line endings to Linux line endings
            content = request_text.replace('\r\n', '\n')

            # deserialized object
            request_json = json.loads(content)

        mockS3 = MockS3Handler()
        mockDb = MockDynamodbHandler()
        mockLogger = MockLogger()
        mockApi = MockAPI(os.path.join(self.resources_dir, 'git_api'),
                          'https://git.door43.org/')
        handler = WebhookHandler(event=request_json,
                                 context=None,
                                 logger=mockLogger,
                                 s3_handler=mockS3,
                                 dynamodb_handler=mockDb,
                                 download_handler=mockApi.download_file)
        with self.assertRaises(Exception) as error_context:
            handler.run()

        self.assertIn('manifest missing dublin_core key "type"',
                      str(error_context.exception))

        self.assertFalse(os.path.isdir(handler.temp_dir))
        mock_instance.add_error.assert_called_once_with(
            'Bad Manifest: manifest missing dublin_core key "type"')
예제 #23
0
    def test_webhook_versification(self, mock_reporter, mock_url_exists):
        """
        We are not currently processing versification.
        Therefore, we test that nothing happens.
        :param mock_report_error:
        :return:
        """
        request_file = os.path.join(self.resources_dir,
                                    'versification-request.json')
        with codecs.open(request_file, 'r', encoding='utf-8') as in_file:
            request_text = in_file.read()
            # convert Windows line endings to Linux line endings
            content = request_text.replace('\r\n', '\n')
            request_json = json.loads(content)

        urls = {
            'https://git.door43.org/Door43-Catalog/versification/archive/c7e936e4dcc103560987c8475db69e292aa66dca.zip':
            'versification.zip'
        }

        mockLogger = MockLogger()
        mock_api = MockAPI(self.resources_dir, 'https://git.door43.org')
        mock_db = MockDynamodbHandler()
        mock_s3 = MockS3Handler()
        handler = WebhookHandler(request_json,
                                 context=None,
                                 s3_handler=mock_s3,
                                 logger=mockLogger,
                                 dynamodb_handler=mock_db,
                                 download_handler=lambda url, dest: mock_api.
                                 download_file(urls[url], dest))
        handler.run()

        self.assertEqual(0, len(mock_s3._recent_uploads))
        data = mock_db._last_inserted_item
        self.assertEqual(None, data)
예제 #24
0
    def test_signing_handler_invalid_manifest(self, mock_reporter):
        mock_instance = MagicMock()
        mock_instance.add_error = MagicMock()
        mock_reporter.return_value = mock_instance

        event = self.create_event()
        mock_db = MockDynamodbHandler()
        mock_db._load_db(os.path.join(self.resources_dir, 'db/invalid.json'))

        mock_s3 = MockS3Handler()
        mock_s3._load_path(os.path.join(self.resources_dir, 'cdn'))

        mock_api = MockAPI(os.path.join(self.resources_dir, 'cdn'),
                           'https://cdn.door43.org')

        mock_logger = MockLogger()

        signer = SigningHandler(event,
                                None,
                                logger=mock_logger,
                                signer=self.mock_signer,
                                s3_handler=mock_s3,
                                dynamodb_handler=mock_db,
                                url_exists_handler=mock_api.url_exists,
                                download_handler=mock_api.download_file)
        result = signer.run()

        self.assertTrue(result)
        for f in mock_s3._recent_uploads:
            # assert nothing was uploaded to production
            self.assertTrue(f.startswith('temp/'))
            self.assertFalse(f.endswith('.sig'))
        # self.assertIn('Skipping unit-test. Bad Manifest: No JSON object could be decoded', mock_logger._messages)
        mock_instance.add_error.assert_called_once_with(
            'Skipping unit-test. Bad Manifest: No JSON object could be decoded'
        )
예제 #25
0
    def test_inprogress(self, mock_reporter):
        mockV3Api = MockAPI(os.path.join(self.resources_dir, 'v3_api'),
                            'https://api.door43.org/')
        mockV3Api.add_host(os.path.join(self.resources_dir, 'v3_cdn'),
                           'https://test-cdn.door43.org/')

        mockV2Api = MockAPI(os.path.join(self.resources_dir, 'ts_api'),
                            'https://test')
        mockS3 = MockS3Handler('ts_bucket')
        mockDb = MockDynamodbHandler()
        mockDb._load_db(
            os.path.join(TestTsV2Catalog.resources_dir,
                         'ready_inprogress_db.json'))

        mockLog = MockLogger()
        event = self.make_event()
        converter = TsV2CatalogHandler(
            event=event,
            context=None,
            logger=mockLog,
            s3_handler=mockS3,
            dynamodb_handler=mockDb,
            url_handler=mockV3Api.get_url,
            download_handler=mockV3Api.download_file,
            url_exists_handler=lambda url: True)
        converter.run()

        assert_s3_equals_api_json(self, mockS3, mockV2Api,
                                  'v2/ts/catalog.json')
        assert_s3_equals_api_json(self, mockS3, mockV2Api,
                                  'v2/ts/obs/languages.json')
        assert_s3_equals_api_json(self, mockS3, mockV2Api,
                                  'v2/ts/obs/en/resources.json')
        self.assertNotIn('v2/ts/obs/en/obs/source.json',
                         mockS3._recent_uploads)
        # assert_s3_equals_api_json(self, mockS3, mockV2Api, 'v2/ts/obs/en/obs/source.json')
        assert_s3_equals_api_json(self, mockS3, mockV2Api,
                                  'v2/ts/obs/en/notes.json')
        assert_s3_equals_api_json(self, mockS3, mockV2Api,
                                  'v2/ts/obs/en/questions.json')
        # we have frozen tw_cat
        self.assertNotIn('v2/ts/obs/en/tw_cat.json', mockS3._recent_uploads)

        assert_s3_equals_api_json(self, mockS3, mockV2Api,
                                  'v2/ts/1ch/languages.json')
        assert_s3_equals_api_json(self, mockS3, mockV2Api,
                                  'v2/ts/1ch/en/resources.json')
        assert_s3_equals_api_json(self, mockS3, mockV2Api,
                                  'v2/ts/1ch/en/ulb/v7/source.json')
        self.assertNotIn('v2/ts/1ch/en/notes.json', mockS3._recent_uploads)
        # assert_s3_equals_api_json(self, mockS3, mockV2Api, 'v2/ts/1ch/en/notes.json')
        assert_s3_equals_api_json(self, mockS3, mockV2Api,
                                  'v2/ts/1ch/en/questions.json')
        self.assertNotIn('v2/ts/1ch/en/tw_cat.json', mockS3._recent_uploads)
        # assert_s3_equals_api_json(self, mockS3, mockV2Api, 'v2/ts/1ch/en/tw_cat.json')

        assert_s3_equals_api_json(self, mockS3, mockV2Api,
                                  'v2/ts/bible/en/words.json')

        # validate urls in generate catalogs match the generated output paths
        root_url = '{}/'.format(
            event['stage-variables']['cdn_url'].rstrip('/'))
        catalog = json.loads(
            read_file(mockS3._recent_uploads['v2/ts/catalog.json']))
        url_err_msg = 'url in catalog does not match upload path: {}'
        for project in catalog:
            lang_catalog_path = project['lang_catalog'].replace(
                root_url, '').split('?')[0]
            self.assertIn(lang_catalog_path, mockS3._recent_uploads,
                          url_err_msg.format(lang_catalog_path))
            lang_catalog = json.loads(
                read_file(mockS3._recent_uploads[lang_catalog_path]))
            for language in lang_catalog:
                res_catalog_path = language['res_catalog'].replace(
                    root_url, '').split('?')[0]
                self.assertIn(res_catalog_path, mockS3._recent_uploads,
                              url_err_msg.format(res_catalog_path))
                res_catalog = json.loads(
                    read_file(mockS3._recent_uploads[res_catalog_path]))
                for resource in res_catalog:
                    questions_path = resource['checking_questions'].replace(
                        root_url, '').split('?')[0]
                    # notes_path = resource['notes'].replace(root_url, '').split('?')[0]
                    # source_path = resource['source'].replace(root_url, '').split('?')[0]
                    terms_path = resource['terms'].replace(root_url,
                                                           '').split('?')[0]
                    # terms_map_path = resource['tw_cat'].replace(root_url, '').split('?')[0]

                    if questions_path:
                        self.assertIn(questions_path, mockS3._recent_uploads,
                                      url_err_msg.format(questions_path))
                    # if notes_path:
                    # self.assertIn(notes_path, mockS3._uploads, url_err_msg.format(notes_path))
                    # if source_path:
                    #     self.assertIn(source_path, mockS3._uploads, url_err_msg.format(source_path))
                    if terms_path:
                        self.assertIn(terms_path, mockS3._recent_uploads,
                                      url_err_msg.format(terms_path))