authentik.admin.files.tests.test_manager
Test file service layer
1"""Test file service layer""" 2 3from unittest import skipUnless 4from unittest.mock import Mock 5from urllib.parse import urlparse 6 7from django.http import HttpRequest 8from django.test import TestCase 9 10from authentik.admin.files.manager import FileManager 11from authentik.admin.files.tests.utils import ( 12 FileTestFileBackendMixin, 13 FileTestS3BackendMixin, 14 s3_test_server_available, 15) 16from authentik.admin.files.usage import FileUsage 17from authentik.lib.config import CONFIG 18 19 20class TestResolveFileUrlBasic(TestCase): 21 def test_resolve_empty_path(self): 22 """Test resolving empty file path""" 23 manager = FileManager(FileUsage.MEDIA) 24 result = manager.file_url("") 25 self.assertEqual(result, "") 26 27 def test_resolve_none_path(self): 28 """Test resolving None file path""" 29 manager = FileManager(FileUsage.MEDIA) 30 result = manager.file_url(None) 31 self.assertEqual(result, "") 32 33 def test_resolve_font_awesome(self): 34 """Test resolving Font Awesome icon""" 35 manager = FileManager(FileUsage.MEDIA) 36 result = manager.file_url("fa://fa-check") 37 self.assertEqual(result, "fa://fa-check") 38 39 def test_resolve_http_url(self): 40 """Test resolving HTTP URL""" 41 manager = FileManager(FileUsage.MEDIA) 42 result = manager.file_url("http://example.com/icon.png") 43 self.assertEqual(result, "http://example.com/icon.png") 44 45 def test_resolve_https_url(self): 46 """Test resolving HTTPS URL""" 47 manager = FileManager(FileUsage.MEDIA) 48 result = manager.file_url("https://example.com/icon.png") 49 self.assertEqual(result, "https://example.com/icon.png") 50 51 def test_resolve_static_path(self): 52 """Test resolving static file path""" 53 manager = FileManager(FileUsage.MEDIA) 54 result = manager.file_url("/static/authentik/sources/icon.svg") 55 self.assertEqual(result, "/static/authentik/sources/icon.svg") 56 57 def test_file_url_forwards_use_cache(self): 58 """Test file_url forwards use_cache to backend.""" 59 manager = FileManager(FileUsage.MEDIA) 60 backend = Mock() 61 backend.supports_file.return_value = True 62 backend.file_url.return_value = "/files/media/public/test.png?token=fresh" 63 manager.backends = [backend] 64 65 result = manager.file_url("test.png", use_cache=False) 66 67 self.assertEqual(result, "/files/media/public/test.png?token=fresh") 68 backend.file_url.assert_called_once_with("test.png", None, use_cache=False) 69 70 71class TestResolveFileUrlFileBackend(FileTestFileBackendMixin, TestCase): 72 def test_resolve_storage_file(self): 73 """Test resolving uploaded storage file""" 74 manager = FileManager(FileUsage.MEDIA) 75 result = manager.file_url("test.png").split("?")[0] 76 self.assertEqual(result, "/files/media/public/test.png") 77 78 def test_resolve_full_static_with_request(self): 79 """Test resolving static file with request builds absolute URI""" 80 mock_request = HttpRequest() 81 mock_request.META = { 82 "HTTP_HOST": "example.com", 83 "SERVER_NAME": "example.com", 84 } 85 86 manager = FileManager(FileUsage.MEDIA) 87 result = manager.file_url("/static/icon.svg", mock_request) 88 89 self.assertEqual(result, "http://example.com/static/icon.svg") 90 91 def test_resolve_full_file_backend_with_request(self): 92 """Test resolving FileBackend file with request""" 93 mock_request = HttpRequest() 94 mock_request.META = { 95 "HTTP_HOST": "example.com", 96 "SERVER_NAME": "example.com", 97 } 98 99 manager = FileManager(FileUsage.MEDIA) 100 result = manager.file_url("test.png", mock_request).split("?")[0] 101 102 self.assertEqual(result, "http://example.com/files/media/public/test.png") 103 104 105@skipUnless(s3_test_server_available(), "S3 test server not available") 106class TestResolveFileUrlS3Backend(FileTestS3BackendMixin, TestCase): 107 @CONFIG.patch("storage.media.s3.custom_domain", "s3.test:8080/test") 108 @CONFIG.patch("storage.media.s3.secure_urls", False) 109 def test_resolve_full_s3_backend(self): 110 """Test resolving S3Backend returns presigned URL as-is""" 111 mock_request = HttpRequest() 112 mock_request.META = { 113 "HTTP_HOST": "example.com", 114 "SERVER_NAME": "example.com", 115 } 116 117 manager = FileManager(FileUsage.MEDIA) 118 result = manager.file_url("test.png", mock_request) 119 120 # S3 URLs should be returned as-is (already absolute) 121 self.assertTrue(result.startswith("http://s3.test:8080/test")) 122 123 124class TestThemedUrls(FileTestFileBackendMixin, TestCase): 125 """Test FileManager.themed_urls method""" 126 127 def test_themed_urls_none_path(self): 128 """Test themed_urls returns None for None path""" 129 manager = FileManager(FileUsage.MEDIA) 130 result = manager.themed_urls(None) 131 self.assertIsNone(result) 132 133 def test_themed_urls_empty_path(self): 134 """Test themed_urls returns None for empty path""" 135 manager = FileManager(FileUsage.MEDIA) 136 result = manager.themed_urls("") 137 self.assertIsNone(result) 138 139 def test_themed_urls_no_theme_variable(self): 140 """Test themed_urls returns None when no %(theme)s in path""" 141 manager = FileManager(FileUsage.MEDIA) 142 result = manager.themed_urls("logo.png") 143 self.assertIsNone(result) 144 145 def test_themed_urls_with_theme_variable(self): 146 """Test themed_urls returns dict of URLs for each theme""" 147 manager = FileManager(FileUsage.MEDIA) 148 result = manager.themed_urls("logo-%(theme)s.png") 149 150 self.assertIsInstance(result, dict) 151 self.assertIn("light", result) 152 self.assertIn("dark", result) 153 self.assertIn("logo-light.png", result["light"]) 154 self.assertIn("logo-dark.png", result["dark"]) 155 156 def test_themed_urls_with_request(self): 157 """Test themed_urls builds absolute URLs with request""" 158 mock_request = HttpRequest() 159 mock_request.META = { 160 "HTTP_HOST": "example.com", 161 "SERVER_NAME": "example.com", 162 } 163 164 manager = FileManager(FileUsage.MEDIA) 165 result = manager.themed_urls("logo-%(theme)s.svg", mock_request) 166 167 self.assertIsInstance(result, dict) 168 light_url = urlparse(result["light"]) 169 dark_url = urlparse(result["dark"]) 170 self.assertEqual(light_url.scheme, "http") 171 self.assertEqual(light_url.netloc, "example.com") 172 self.assertEqual(dark_url.scheme, "http") 173 self.assertEqual(dark_url.netloc, "example.com") 174 175 def test_themed_urls_passthrough_with_theme_variable(self): 176 """Test themed_urls returns dict for passthrough URLs with %(theme)s""" 177 manager = FileManager(FileUsage.MEDIA) 178 # External URLs with %(theme)s should return themed URLs 179 result = manager.themed_urls("https://example.com/logo-%(theme)s.png") 180 self.assertIsInstance(result, dict) 181 self.assertEqual(result["light"], "https://example.com/logo-light.png") 182 self.assertEqual(result["dark"], "https://example.com/logo-dark.png") 183 184 def test_themed_urls_passthrough_without_theme_variable(self): 185 """Test themed_urls returns None for passthrough URLs without %(theme)s""" 186 manager = FileManager(FileUsage.MEDIA) 187 # External URLs without %(theme)s should return None 188 result = manager.themed_urls("https://example.com/logo.png") 189 self.assertIsNone(result)
21class TestResolveFileUrlBasic(TestCase): 22 def test_resolve_empty_path(self): 23 """Test resolving empty file path""" 24 manager = FileManager(FileUsage.MEDIA) 25 result = manager.file_url("") 26 self.assertEqual(result, "") 27 28 def test_resolve_none_path(self): 29 """Test resolving None file path""" 30 manager = FileManager(FileUsage.MEDIA) 31 result = manager.file_url(None) 32 self.assertEqual(result, "") 33 34 def test_resolve_font_awesome(self): 35 """Test resolving Font Awesome icon""" 36 manager = FileManager(FileUsage.MEDIA) 37 result = manager.file_url("fa://fa-check") 38 self.assertEqual(result, "fa://fa-check") 39 40 def test_resolve_http_url(self): 41 """Test resolving HTTP URL""" 42 manager = FileManager(FileUsage.MEDIA) 43 result = manager.file_url("http://example.com/icon.png") 44 self.assertEqual(result, "http://example.com/icon.png") 45 46 def test_resolve_https_url(self): 47 """Test resolving HTTPS URL""" 48 manager = FileManager(FileUsage.MEDIA) 49 result = manager.file_url("https://example.com/icon.png") 50 self.assertEqual(result, "https://example.com/icon.png") 51 52 def test_resolve_static_path(self): 53 """Test resolving static file path""" 54 manager = FileManager(FileUsage.MEDIA) 55 result = manager.file_url("/static/authentik/sources/icon.svg") 56 self.assertEqual(result, "/static/authentik/sources/icon.svg") 57 58 def test_file_url_forwards_use_cache(self): 59 """Test file_url forwards use_cache to backend.""" 60 manager = FileManager(FileUsage.MEDIA) 61 backend = Mock() 62 backend.supports_file.return_value = True 63 backend.file_url.return_value = "/files/media/public/test.png?token=fresh" 64 manager.backends = [backend] 65 66 result = manager.file_url("test.png", use_cache=False) 67 68 self.assertEqual(result, "/files/media/public/test.png?token=fresh") 69 backend.file_url.assert_called_once_with("test.png", None, use_cache=False)
Similar to TransactionTestCase, but use transaction.atomic() to achieve
test isolation.
In most situations, TestCase should be preferred to TransactionTestCase as it allows faster execution. However, there are some situations where using TransactionTestCase might be necessary (e.g. testing some transactional behavior).
On database backends with no transaction support, TestCase behaves as TransactionTestCase.
22 def test_resolve_empty_path(self): 23 """Test resolving empty file path""" 24 manager = FileManager(FileUsage.MEDIA) 25 result = manager.file_url("") 26 self.assertEqual(result, "")
Test resolving empty file path
28 def test_resolve_none_path(self): 29 """Test resolving None file path""" 30 manager = FileManager(FileUsage.MEDIA) 31 result = manager.file_url(None) 32 self.assertEqual(result, "")
Test resolving None file path
34 def test_resolve_font_awesome(self): 35 """Test resolving Font Awesome icon""" 36 manager = FileManager(FileUsage.MEDIA) 37 result = manager.file_url("fa://fa-check") 38 self.assertEqual(result, "fa://fa-check")
Test resolving Font Awesome icon
40 def test_resolve_http_url(self): 41 """Test resolving HTTP URL""" 42 manager = FileManager(FileUsage.MEDIA) 43 result = manager.file_url("http://example.com/icon.png") 44 self.assertEqual(result, "http://example.com/icon.png")
Test resolving HTTP URL
46 def test_resolve_https_url(self): 47 """Test resolving HTTPS URL""" 48 manager = FileManager(FileUsage.MEDIA) 49 result = manager.file_url("https://example.com/icon.png") 50 self.assertEqual(result, "https://example.com/icon.png")
Test resolving HTTPS URL
52 def test_resolve_static_path(self): 53 """Test resolving static file path""" 54 manager = FileManager(FileUsage.MEDIA) 55 result = manager.file_url("/static/authentik/sources/icon.svg") 56 self.assertEqual(result, "/static/authentik/sources/icon.svg")
Test resolving static file path
58 def test_file_url_forwards_use_cache(self): 59 """Test file_url forwards use_cache to backend.""" 60 manager = FileManager(FileUsage.MEDIA) 61 backend = Mock() 62 backend.supports_file.return_value = True 63 backend.file_url.return_value = "/files/media/public/test.png?token=fresh" 64 manager.backends = [backend] 65 66 result = manager.file_url("test.png", use_cache=False) 67 68 self.assertEqual(result, "/files/media/public/test.png?token=fresh") 69 backend.file_url.assert_called_once_with("test.png", None, use_cache=False)
Test file_url forwards use_cache to backend.
72class TestResolveFileUrlFileBackend(FileTestFileBackendMixin, TestCase): 73 def test_resolve_storage_file(self): 74 """Test resolving uploaded storage file""" 75 manager = FileManager(FileUsage.MEDIA) 76 result = manager.file_url("test.png").split("?")[0] 77 self.assertEqual(result, "/files/media/public/test.png") 78 79 def test_resolve_full_static_with_request(self): 80 """Test resolving static file with request builds absolute URI""" 81 mock_request = HttpRequest() 82 mock_request.META = { 83 "HTTP_HOST": "example.com", 84 "SERVER_NAME": "example.com", 85 } 86 87 manager = FileManager(FileUsage.MEDIA) 88 result = manager.file_url("/static/icon.svg", mock_request) 89 90 self.assertEqual(result, "http://example.com/static/icon.svg") 91 92 def test_resolve_full_file_backend_with_request(self): 93 """Test resolving FileBackend file with request""" 94 mock_request = HttpRequest() 95 mock_request.META = { 96 "HTTP_HOST": "example.com", 97 "SERVER_NAME": "example.com", 98 } 99 100 manager = FileManager(FileUsage.MEDIA) 101 result = manager.file_url("test.png", mock_request).split("?")[0] 102 103 self.assertEqual(result, "http://example.com/files/media/public/test.png")
Similar to TransactionTestCase, but use transaction.atomic() to achieve
test isolation.
In most situations, TestCase should be preferred to TransactionTestCase as it allows faster execution. However, there are some situations where using TransactionTestCase might be necessary (e.g. testing some transactional behavior).
On database backends with no transaction support, TestCase behaves as TransactionTestCase.
73 def test_resolve_storage_file(self): 74 """Test resolving uploaded storage file""" 75 manager = FileManager(FileUsage.MEDIA) 76 result = manager.file_url("test.png").split("?")[0] 77 self.assertEqual(result, "/files/media/public/test.png")
Test resolving uploaded storage file
79 def test_resolve_full_static_with_request(self): 80 """Test resolving static file with request builds absolute URI""" 81 mock_request = HttpRequest() 82 mock_request.META = { 83 "HTTP_HOST": "example.com", 84 "SERVER_NAME": "example.com", 85 } 86 87 manager = FileManager(FileUsage.MEDIA) 88 result = manager.file_url("/static/icon.svg", mock_request) 89 90 self.assertEqual(result, "http://example.com/static/icon.svg")
Test resolving static file with request builds absolute URI
92 def test_resolve_full_file_backend_with_request(self): 93 """Test resolving FileBackend file with request""" 94 mock_request = HttpRequest() 95 mock_request.META = { 96 "HTTP_HOST": "example.com", 97 "SERVER_NAME": "example.com", 98 } 99 100 manager = FileManager(FileUsage.MEDIA) 101 result = manager.file_url("test.png", mock_request).split("?")[0] 102 103 self.assertEqual(result, "http://example.com/files/media/public/test.png")
Test resolving FileBackend file with request
Inherited Members
106@skipUnless(s3_test_server_available(), "S3 test server not available") 107class TestResolveFileUrlS3Backend(FileTestS3BackendMixin, TestCase): 108 @CONFIG.patch("storage.media.s3.custom_domain", "s3.test:8080/test") 109 @CONFIG.patch("storage.media.s3.secure_urls", False) 110 def test_resolve_full_s3_backend(self): 111 """Test resolving S3Backend returns presigned URL as-is""" 112 mock_request = HttpRequest() 113 mock_request.META = { 114 "HTTP_HOST": "example.com", 115 "SERVER_NAME": "example.com", 116 } 117 118 manager = FileManager(FileUsage.MEDIA) 119 result = manager.file_url("test.png", mock_request) 120 121 # S3 URLs should be returned as-is (already absolute) 122 self.assertTrue(result.startswith("http://s3.test:8080/test"))
Similar to TransactionTestCase, but use transaction.atomic() to achieve
test isolation.
In most situations, TestCase should be preferred to TransactionTestCase as it allows faster execution. However, there are some situations where using TransactionTestCase might be necessary (e.g. testing some transactional behavior).
On database backends with no transaction support, TestCase behaves as TransactionTestCase.
108 @CONFIG.patch("storage.media.s3.custom_domain", "s3.test:8080/test") 109 @CONFIG.patch("storage.media.s3.secure_urls", False) 110 def test_resolve_full_s3_backend(self): 111 """Test resolving S3Backend returns presigned URL as-is""" 112 mock_request = HttpRequest() 113 mock_request.META = { 114 "HTTP_HOST": "example.com", 115 "SERVER_NAME": "example.com", 116 } 117 118 manager = FileManager(FileUsage.MEDIA) 119 result = manager.file_url("test.png", mock_request) 120 121 # S3 URLs should be returned as-is (already absolute) 122 self.assertTrue(result.startswith("http://s3.test:8080/test"))
Test resolving S3Backend returns presigned URL as-is
Inherited Members
125class TestThemedUrls(FileTestFileBackendMixin, TestCase): 126 """Test FileManager.themed_urls method""" 127 128 def test_themed_urls_none_path(self): 129 """Test themed_urls returns None for None path""" 130 manager = FileManager(FileUsage.MEDIA) 131 result = manager.themed_urls(None) 132 self.assertIsNone(result) 133 134 def test_themed_urls_empty_path(self): 135 """Test themed_urls returns None for empty path""" 136 manager = FileManager(FileUsage.MEDIA) 137 result = manager.themed_urls("") 138 self.assertIsNone(result) 139 140 def test_themed_urls_no_theme_variable(self): 141 """Test themed_urls returns None when no %(theme)s in path""" 142 manager = FileManager(FileUsage.MEDIA) 143 result = manager.themed_urls("logo.png") 144 self.assertIsNone(result) 145 146 def test_themed_urls_with_theme_variable(self): 147 """Test themed_urls returns dict of URLs for each theme""" 148 manager = FileManager(FileUsage.MEDIA) 149 result = manager.themed_urls("logo-%(theme)s.png") 150 151 self.assertIsInstance(result, dict) 152 self.assertIn("light", result) 153 self.assertIn("dark", result) 154 self.assertIn("logo-light.png", result["light"]) 155 self.assertIn("logo-dark.png", result["dark"]) 156 157 def test_themed_urls_with_request(self): 158 """Test themed_urls builds absolute URLs with request""" 159 mock_request = HttpRequest() 160 mock_request.META = { 161 "HTTP_HOST": "example.com", 162 "SERVER_NAME": "example.com", 163 } 164 165 manager = FileManager(FileUsage.MEDIA) 166 result = manager.themed_urls("logo-%(theme)s.svg", mock_request) 167 168 self.assertIsInstance(result, dict) 169 light_url = urlparse(result["light"]) 170 dark_url = urlparse(result["dark"]) 171 self.assertEqual(light_url.scheme, "http") 172 self.assertEqual(light_url.netloc, "example.com") 173 self.assertEqual(dark_url.scheme, "http") 174 self.assertEqual(dark_url.netloc, "example.com") 175 176 def test_themed_urls_passthrough_with_theme_variable(self): 177 """Test themed_urls returns dict for passthrough URLs with %(theme)s""" 178 manager = FileManager(FileUsage.MEDIA) 179 # External URLs with %(theme)s should return themed URLs 180 result = manager.themed_urls("https://example.com/logo-%(theme)s.png") 181 self.assertIsInstance(result, dict) 182 self.assertEqual(result["light"], "https://example.com/logo-light.png") 183 self.assertEqual(result["dark"], "https://example.com/logo-dark.png") 184 185 def test_themed_urls_passthrough_without_theme_variable(self): 186 """Test themed_urls returns None for passthrough URLs without %(theme)s""" 187 manager = FileManager(FileUsage.MEDIA) 188 # External URLs without %(theme)s should return None 189 result = manager.themed_urls("https://example.com/logo.png") 190 self.assertIsNone(result)
Test FileManager.themed_urls method
128 def test_themed_urls_none_path(self): 129 """Test themed_urls returns None for None path""" 130 manager = FileManager(FileUsage.MEDIA) 131 result = manager.themed_urls(None) 132 self.assertIsNone(result)
Test themed_urls returns None for None path
134 def test_themed_urls_empty_path(self): 135 """Test themed_urls returns None for empty path""" 136 manager = FileManager(FileUsage.MEDIA) 137 result = manager.themed_urls("") 138 self.assertIsNone(result)
Test themed_urls returns None for empty path
140 def test_themed_urls_no_theme_variable(self): 141 """Test themed_urls returns None when no %(theme)s in path""" 142 manager = FileManager(FileUsage.MEDIA) 143 result = manager.themed_urls("logo.png") 144 self.assertIsNone(result)
Test themed_urls returns None when no %(theme)s in path
146 def test_themed_urls_with_theme_variable(self): 147 """Test themed_urls returns dict of URLs for each theme""" 148 manager = FileManager(FileUsage.MEDIA) 149 result = manager.themed_urls("logo-%(theme)s.png") 150 151 self.assertIsInstance(result, dict) 152 self.assertIn("light", result) 153 self.assertIn("dark", result) 154 self.assertIn("logo-light.png", result["light"]) 155 self.assertIn("logo-dark.png", result["dark"])
Test themed_urls returns dict of URLs for each theme
157 def test_themed_urls_with_request(self): 158 """Test themed_urls builds absolute URLs with request""" 159 mock_request = HttpRequest() 160 mock_request.META = { 161 "HTTP_HOST": "example.com", 162 "SERVER_NAME": "example.com", 163 } 164 165 manager = FileManager(FileUsage.MEDIA) 166 result = manager.themed_urls("logo-%(theme)s.svg", mock_request) 167 168 self.assertIsInstance(result, dict) 169 light_url = urlparse(result["light"]) 170 dark_url = urlparse(result["dark"]) 171 self.assertEqual(light_url.scheme, "http") 172 self.assertEqual(light_url.netloc, "example.com") 173 self.assertEqual(dark_url.scheme, "http") 174 self.assertEqual(dark_url.netloc, "example.com")
Test themed_urls builds absolute URLs with request
176 def test_themed_urls_passthrough_with_theme_variable(self): 177 """Test themed_urls returns dict for passthrough URLs with %(theme)s""" 178 manager = FileManager(FileUsage.MEDIA) 179 # External URLs with %(theme)s should return themed URLs 180 result = manager.themed_urls("https://example.com/logo-%(theme)s.png") 181 self.assertIsInstance(result, dict) 182 self.assertEqual(result["light"], "https://example.com/logo-light.png") 183 self.assertEqual(result["dark"], "https://example.com/logo-dark.png")
Test themed_urls returns dict for passthrough URLs with %(theme)s
185 def test_themed_urls_passthrough_without_theme_variable(self): 186 """Test themed_urls returns None for passthrough URLs without %(theme)s""" 187 manager = FileManager(FileUsage.MEDIA) 188 # External URLs without %(theme)s should return None 189 result = manager.themed_urls("https://example.com/logo.png") 190 self.assertIsNone(result)
Test themed_urls returns None for passthrough URLs without %(theme)s