def test_path_info_passed_to_sender(): token_config = TokenConfig(_SECRET) sender_app = _EnvironRecordingApp() app = AuthTokenApplication(_PROTECTED_DIR, token_config, sender_app) app_tester = _TestApp(app) url_path = token_config.get_url_path(_EXPECTED_ASCII_TOKEN_FILE_NAME) app_tester.get(url_path, status=200) eq_("/" + _EXPECTED_ASCII_TOKEN_FILE_NAME, sender_app.environ["PATH_INFO"])
def test_existing_file_with_non_ascii_characters(self): """Unicode characters are supported in file names.""" config = TokenConfig(_SECRET, timeout=120) app = _TestApp(AuthTokenApplication(_PROTECTED_DIR, config)) url_path = config.get_url_path(_NON_ASCII_FILE_NAME) urlencoded_file = _EXPECTED_NON_ASCII_TOKEN_FILE_NAME_ENCODED response = app.get(url_path, status=200) ok_("X-Sendfile" in response.headers) ok_(response.headers['X-Sendfile'].endswith(urlencoded_file))
def test_non_ascii_url_path_generation(self): config = TokenConfig(_SECRET, timeout=120) expected_path = "/%s-%s/%s" % ( _EXPECTED_NON_ASCII_TOKEN_DIGEST, _FIXED_TIME_HEX, _EXPECTED_NON_ASCII_TOKEN_FILE_NAME_ENCODED, ) generated_path = config._generate_url_path(_NON_ASCII_FILE_NAME, _FIXED_TIME) eq_(generated_path, expected_path)
def setUp(self): self.config = TokenConfig(_SECRET, timeout=120) self.app = _TestApp(AuthTokenApplication(_PROTECTED_DIR, self.config))
class TestAuthTokenApp(object): """Acceptance tests for the auth token WGSI application.""" def setUp(self): self.config = TokenConfig(_SECRET, timeout=120) self.app = _TestApp(AuthTokenApplication(_PROTECTED_DIR, self.config)) def test_expired_token(self): """Files with expired tokens are not served; 410 response is given.""" five_minutes_ago = _EPOCH - timedelta(minutes=5) url_path = self.config._generate_url_path(_EXPECTED_ASCII_TOKEN_FILE_NAME, five_minutes_ago) self.app.get(url_path, status=410) def test_invalid_digest(self): """Files with invalid digests are not served; 404 response is given.""" # Let's change a few characters in the digest part of the URL: good_url_path = self.config._generate_url_path(_EXPECTED_ASCII_TOKEN_FILE_NAME, datetime.now()) bad_url_path = good_url_path[:3] + "xyz" + good_url_path[6:] self.app.get(bad_url_path, status=404) def test_invalid_timestamps(self): """ Files with invalid timestamps are not served; 404 response is given. """ bad_timestamp = "xyz" url_path = "/%s-%s/%s" % (_EXPECTED_ASCII_TOKEN_DIGEST, bad_timestamp, _EXPECTED_ASCII_TOKEN_FILE_NAME) self.app.get(url_path, status=404) def test_no_token(self): """Files requested without token are not served; a 404 is returned.""" self.app.get("/%s" % _EXPECTED_ASCII_TOKEN_FILE_NAME, status=404) def test_good_token_and_existing_file(self): """Existing files requested with valid token are served.""" url_path = self.config.get_url_path(_EXPECTED_ASCII_TOKEN_FILE_NAME) response = self.app.get(url_path, status=200) ok_("X-Sendfile" in response.headers) xsendfile_value = response.headers["X-Sendfile"] ok_(xsendfile_value.endswith(_EXPECTED_ASCII_TOKEN_FILE_NAME)) def test_good_token_and_existing_file_in_sub_directory(self): """ Existing files in a sub-directory requested with valid token are served. """ url_path = self.config.get_url_path(_SUB_DIRECTORY_FILE) response = self.app.get(url_path, status=200) ok_("X-Sendfile" in response.headers) ok_(response.headers["X-Sendfile"].endswith(_SUB_DIRECTORY_FILE)) def test_existing_file_with_non_ascii_characters(self): """Unicode characters are supported in file names.""" config = TokenConfig(_SECRET, timeout=120) app = _TestApp(AuthTokenApplication(_PROTECTED_DIR, config)) url_path = config.get_url_path(_NON_ASCII_FILE_NAME) response = app.get(url_path, status=200) ok_("X-Sendfile" in response.headers) urlencoded_file = _EXPECTED_NON_ASCII_TOKEN_FILE_NAME_ENCODED ok_(response.headers["X-Sendfile"].endswith(urlencoded_file)) @staticmethod def test_path_info_passed_to_sender(): token_config = TokenConfig(_SECRET) sender_app = _EnvironRecordingApp() app = AuthTokenApplication(_PROTECTED_DIR, token_config, sender_app) app_tester = _TestApp(app) url_path = token_config.get_url_path(_EXPECTED_ASCII_TOKEN_FILE_NAME) app_tester.get(url_path, status=200) eq_("/" + _EXPECTED_ASCII_TOKEN_FILE_NAME, sender_app.environ["PATH_INFO"])
def setUp(self): self.config = TokenConfig(_SECRET, timeout=120)
class TestTokenConfig(object): """Unit tests for the the token configuration.""" def setUp(self): self.config = TokenConfig(_SECRET, timeout=120) # { Checking the hashing algorithm validation in the constructor def test_known_hashing_algorithm(self): """Built-in hashing algorithms are supported out-of-the-box.""" TokenConfig("s3cr3t", "sha1") def test_unknown_hashling_algorith(self): """Unknown hashing algo identifiers are caught.""" assert_raises(ValueError, TokenConfig, "s2cr3t", "non-existing") def test_custom_hashling_algorith(self): """Custom hashing functions are supported if they are callable.""" TokenConfig("s2cr3t", _IDENTITY_HASH_ALGO) # { Tests for the token expiration verification def test_expired_token(self): """Expired tokens must be caught.""" five_minutes_ago = _EPOCH - timedelta(minutes=5) assert_false(self.config.is_current(five_minutes_ago)) def test_current_token(self): """Tokens which have not timed out are obviously taken.""" ok_(self.config.is_current(datetime.now())) def test_future_token(self): """Future tokens are accepted.""" five_hours_later = _EPOCH + timedelta(hours=5) ok_(self.config.is_current(five_hours_later)) # { Tests for the token digest validation def test_validating_invalid_digest(self): bad_digest = "5d41402abc4b2a76b9719d911017c592" is_valid_digest = self.config.is_valid_digest(bad_digest, _EXPECTED_ASCII_TOKEN_FILE_NAME, _FIXED_TIME) assert_false(is_valid_digest) def test_validating_valid_digest(self): is_valid_digest = self.config.is_valid_digest( _EXPECTED_ASCII_TOKEN_DIGEST, _EXPECTED_ASCII_TOKEN_FILE_NAME, _FIXED_TIME ) ok_(is_valid_digest) # } def test_url_path_generation(self): """ The generated URL must include the token, the timestamp and the requested file. The result is compared against a known good URL path. """ generated_path = self.config._generate_url_path(_EXPECTED_ASCII_TOKEN_FILE_NAME, _FIXED_TIME) eq_(generated_path, _EXPECTED_ASCII_TOKEN_PATH) def test_non_ascii_url_path_generation(self): config = TokenConfig(_SECRET, timeout=120) expected_path = "/%s-%s/%s" % ( _EXPECTED_NON_ASCII_TOKEN_DIGEST, _FIXED_TIME_HEX, _EXPECTED_NON_ASCII_TOKEN_FILE_NAME_ENCODED, ) generated_path = config._generate_url_path(_NON_ASCII_FILE_NAME, _FIXED_TIME) eq_(generated_path, expected_path)