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