authentik.admin.files.backends.tests.test_file_backend
1from pathlib import Path 2 3from django.test import TestCase 4 5from authentik.admin.files.backends.file import FileBackend 6from authentik.admin.files.tests.utils import FileTestFileBackendMixin 7from authentik.admin.files.usage import FileUsage 8from authentik.lib.config import CONFIG 9 10 11class TestFileBackend(FileTestFileBackendMixin, TestCase): 12 """Test FileBackend class""" 13 14 def setUp(self): 15 """Set up test fixtures""" 16 super().setUp() 17 self.backend = FileBackend(FileUsage.MEDIA) 18 19 def test_allowed_usages(self): 20 """Test that FileBackend supports all usage types""" 21 self.assertEqual(self.backend.allowed_usages, list(FileUsage)) 22 23 def test_base_path(self): 24 """Test base_path property constructs correct path""" 25 base_path = self.backend.base_path 26 27 expected = Path(self.media_backend_path) / "media" / "public" 28 self.assertEqual(base_path, expected) 29 30 def test_base_path_reports_usage(self): 31 """Test base_path with reports usage""" 32 backend = FileBackend(FileUsage.REPORTS) 33 base_path = backend.base_path 34 35 expected = Path(self.reports_backend_path) / "reports" / "public" 36 self.assertEqual(base_path, expected) 37 38 def test_list_files_empty_directory(self): 39 """Test list_files returns empty when directory is empty""" 40 # Create the directory but keep it empty 41 self.backend.base_path.mkdir(parents=True, exist_ok=True) 42 43 files = list(self.backend.list_files()) 44 self.assertEqual(files, []) 45 46 def test_list_files_with_files(self): 47 """Test list_files returns all files in directory""" 48 base_path = self.backend.base_path 49 base_path.mkdir(parents=True, exist_ok=True) 50 51 # Create some test files 52 (base_path / "file1.txt").write_text("content1") 53 (base_path / "file2.png").write_text("content2") 54 (base_path / "subdir").mkdir() 55 (base_path / "subdir" / "file3.csv").write_text("content3") 56 57 files = sorted(list(self.backend.list_files())) 58 expected = sorted(["file1.txt", "file2.png", "subdir/file3.csv"]) 59 self.assertEqual(files, expected) 60 61 def test_list_files_nonexistent_directory(self): 62 """Test list_files returns empty when directory doesn't exist""" 63 files = list(self.backend.list_files()) 64 self.assertEqual(files, []) 65 66 def test_save_file(self): 67 content = b"test file content" 68 file_name = "test.txt" 69 70 self.backend.save_file(file_name, content) 71 72 # Verify file was created 73 file_path = self.backend.base_path / file_name 74 self.assertTrue(file_path.exists()) 75 self.assertEqual(file_path.read_bytes(), content) 76 77 def test_save_file_creates_subdirectories(self): 78 """Test save_file creates parent directories as needed""" 79 content = b"nested file content" 80 file_name = "subdir1/subdir2/nested.txt" 81 82 self.backend.save_file(file_name, content) 83 84 # Verify file and directories were created 85 file_path = self.backend.base_path / file_name 86 self.assertTrue(file_path.exists()) 87 self.assertEqual(file_path.read_bytes(), content) 88 89 def test_save_file_stream(self): 90 """Test save_file_stream context manager writes file correctly""" 91 content = b"streamed content" 92 file_name = "stream_test.txt" 93 94 with self.backend.save_file_stream(file_name) as f: 95 f.write(content) 96 97 # Verify file was created 98 file_path = self.backend.base_path / file_name 99 self.assertTrue(file_path.exists()) 100 self.assertEqual(file_path.read_bytes(), content) 101 102 def test_save_file_stream_creates_subdirectories(self): 103 """Test save_file_stream creates parent directories as needed""" 104 content = b"nested stream content" 105 file_name = "dir1/dir2/stream.bin" 106 107 with self.backend.save_file_stream(file_name) as f: 108 f.write(content) 109 110 # Verify file and directories were created 111 file_path = self.backend.base_path / file_name 112 self.assertTrue(file_path.exists()) 113 self.assertEqual(file_path.read_bytes(), content) 114 115 def test_delete_file(self): 116 """Test delete_file removes existing file""" 117 file_name = "to_delete.txt" 118 119 # Create file first 120 self.backend.save_file(file_name, b"content") 121 file_path = self.backend.base_path / file_name 122 self.assertTrue(file_path.exists()) 123 124 # Delete it 125 self.backend.delete_file(file_name) 126 self.assertFalse(file_path.exists()) 127 128 def test_delete_file_nonexistent(self): 129 """Test delete_file handles nonexistent file gracefully""" 130 file_name = "does_not_exist.txt" 131 self.backend.delete_file(file_name) 132 133 def test_file_url(self): 134 """Test file_url generates correct URL""" 135 file_name = "icon.png" 136 137 url = self.backend.file_url(file_name).split("?")[0] 138 expected = "/files/media/public/icon.png" 139 self.assertEqual(url, expected) 140 141 @CONFIG.patch("web.path", "/authentik/") 142 def test_file_url_with_prefix(self): 143 """Test file_url with web path prefix""" 144 file_name = "logo.svg" 145 146 url = self.backend.file_url(file_name).split("?")[0] 147 expected = "/authentik/files/media/public/logo.svg" 148 self.assertEqual(url, expected) 149 150 def test_file_url_nested_path(self): 151 """Test file_url with nested file path""" 152 file_name = "path/to/file.png" 153 154 url = self.backend.file_url(file_name).split("?")[0] 155 expected = "/files/media/public/path/to/file.png" 156 self.assertEqual(url, expected) 157 158 def test_file_exists_true(self): 159 """Test file_exists returns True for existing file""" 160 file_name = "exists.txt" 161 self.backend.base_path.mkdir(parents=True, exist_ok=True) 162 (self.backend.base_path / file_name).touch() 163 self.assertTrue(self.backend.file_exists(file_name)) 164 165 def test_file_exists_false(self): 166 """Test file_exists returns False for nonexistent file""" 167 self.assertFalse(self.backend.file_exists("does_not_exist.txt")) 168 169 def test_themed_urls_without_theme_variable(self): 170 """Test themed_urls returns None when filename has no %(theme)s""" 171 file_name = "logo.png" 172 result = self.backend.themed_urls(file_name) 173 self.assertIsNone(result) 174 175 def test_themed_urls_with_theme_variable(self): 176 """Test themed_urls returns dict of URLs for each theme""" 177 file_name = "logo-%(theme)s.png" 178 result = self.backend.themed_urls(file_name) 179 180 self.assertIsInstance(result, dict) 181 self.assertIn("light", result) 182 self.assertIn("dark", result) 183 184 # Check URLs contain the substituted theme 185 self.assertIn("logo-light.png", result["light"]) 186 self.assertIn("logo-dark.png", result["dark"]) 187 188 def test_themed_urls_multiple_theme_variables(self): 189 """Test themed_urls with multiple %(theme)s in path""" 190 file_name = "%(theme)s/logo-%(theme)s.svg" 191 result = self.backend.themed_urls(file_name) 192 193 self.assertIsInstance(result, dict) 194 self.assertIn("light/logo-light.svg", result["light"]) 195 self.assertIn("dark/logo-dark.svg", result["dark"])
12class TestFileBackend(FileTestFileBackendMixin, TestCase): 13 """Test FileBackend class""" 14 15 def setUp(self): 16 """Set up test fixtures""" 17 super().setUp() 18 self.backend = FileBackend(FileUsage.MEDIA) 19 20 def test_allowed_usages(self): 21 """Test that FileBackend supports all usage types""" 22 self.assertEqual(self.backend.allowed_usages, list(FileUsage)) 23 24 def test_base_path(self): 25 """Test base_path property constructs correct path""" 26 base_path = self.backend.base_path 27 28 expected = Path(self.media_backend_path) / "media" / "public" 29 self.assertEqual(base_path, expected) 30 31 def test_base_path_reports_usage(self): 32 """Test base_path with reports usage""" 33 backend = FileBackend(FileUsage.REPORTS) 34 base_path = backend.base_path 35 36 expected = Path(self.reports_backend_path) / "reports" / "public" 37 self.assertEqual(base_path, expected) 38 39 def test_list_files_empty_directory(self): 40 """Test list_files returns empty when directory is empty""" 41 # Create the directory but keep it empty 42 self.backend.base_path.mkdir(parents=True, exist_ok=True) 43 44 files = list(self.backend.list_files()) 45 self.assertEqual(files, []) 46 47 def test_list_files_with_files(self): 48 """Test list_files returns all files in directory""" 49 base_path = self.backend.base_path 50 base_path.mkdir(parents=True, exist_ok=True) 51 52 # Create some test files 53 (base_path / "file1.txt").write_text("content1") 54 (base_path / "file2.png").write_text("content2") 55 (base_path / "subdir").mkdir() 56 (base_path / "subdir" / "file3.csv").write_text("content3") 57 58 files = sorted(list(self.backend.list_files())) 59 expected = sorted(["file1.txt", "file2.png", "subdir/file3.csv"]) 60 self.assertEqual(files, expected) 61 62 def test_list_files_nonexistent_directory(self): 63 """Test list_files returns empty when directory doesn't exist""" 64 files = list(self.backend.list_files()) 65 self.assertEqual(files, []) 66 67 def test_save_file(self): 68 content = b"test file content" 69 file_name = "test.txt" 70 71 self.backend.save_file(file_name, content) 72 73 # Verify file was created 74 file_path = self.backend.base_path / file_name 75 self.assertTrue(file_path.exists()) 76 self.assertEqual(file_path.read_bytes(), content) 77 78 def test_save_file_creates_subdirectories(self): 79 """Test save_file creates parent directories as needed""" 80 content = b"nested file content" 81 file_name = "subdir1/subdir2/nested.txt" 82 83 self.backend.save_file(file_name, content) 84 85 # Verify file and directories were created 86 file_path = self.backend.base_path / file_name 87 self.assertTrue(file_path.exists()) 88 self.assertEqual(file_path.read_bytes(), content) 89 90 def test_save_file_stream(self): 91 """Test save_file_stream context manager writes file correctly""" 92 content = b"streamed content" 93 file_name = "stream_test.txt" 94 95 with self.backend.save_file_stream(file_name) as f: 96 f.write(content) 97 98 # Verify file was created 99 file_path = self.backend.base_path / file_name 100 self.assertTrue(file_path.exists()) 101 self.assertEqual(file_path.read_bytes(), content) 102 103 def test_save_file_stream_creates_subdirectories(self): 104 """Test save_file_stream creates parent directories as needed""" 105 content = b"nested stream content" 106 file_name = "dir1/dir2/stream.bin" 107 108 with self.backend.save_file_stream(file_name) as f: 109 f.write(content) 110 111 # Verify file and directories were created 112 file_path = self.backend.base_path / file_name 113 self.assertTrue(file_path.exists()) 114 self.assertEqual(file_path.read_bytes(), content) 115 116 def test_delete_file(self): 117 """Test delete_file removes existing file""" 118 file_name = "to_delete.txt" 119 120 # Create file first 121 self.backend.save_file(file_name, b"content") 122 file_path = self.backend.base_path / file_name 123 self.assertTrue(file_path.exists()) 124 125 # Delete it 126 self.backend.delete_file(file_name) 127 self.assertFalse(file_path.exists()) 128 129 def test_delete_file_nonexistent(self): 130 """Test delete_file handles nonexistent file gracefully""" 131 file_name = "does_not_exist.txt" 132 self.backend.delete_file(file_name) 133 134 def test_file_url(self): 135 """Test file_url generates correct URL""" 136 file_name = "icon.png" 137 138 url = self.backend.file_url(file_name).split("?")[0] 139 expected = "/files/media/public/icon.png" 140 self.assertEqual(url, expected) 141 142 @CONFIG.patch("web.path", "/authentik/") 143 def test_file_url_with_prefix(self): 144 """Test file_url with web path prefix""" 145 file_name = "logo.svg" 146 147 url = self.backend.file_url(file_name).split("?")[0] 148 expected = "/authentik/files/media/public/logo.svg" 149 self.assertEqual(url, expected) 150 151 def test_file_url_nested_path(self): 152 """Test file_url with nested file path""" 153 file_name = "path/to/file.png" 154 155 url = self.backend.file_url(file_name).split("?")[0] 156 expected = "/files/media/public/path/to/file.png" 157 self.assertEqual(url, expected) 158 159 def test_file_exists_true(self): 160 """Test file_exists returns True for existing file""" 161 file_name = "exists.txt" 162 self.backend.base_path.mkdir(parents=True, exist_ok=True) 163 (self.backend.base_path / file_name).touch() 164 self.assertTrue(self.backend.file_exists(file_name)) 165 166 def test_file_exists_false(self): 167 """Test file_exists returns False for nonexistent file""" 168 self.assertFalse(self.backend.file_exists("does_not_exist.txt")) 169 170 def test_themed_urls_without_theme_variable(self): 171 """Test themed_urls returns None when filename has no %(theme)s""" 172 file_name = "logo.png" 173 result = self.backend.themed_urls(file_name) 174 self.assertIsNone(result) 175 176 def test_themed_urls_with_theme_variable(self): 177 """Test themed_urls returns dict of URLs for each theme""" 178 file_name = "logo-%(theme)s.png" 179 result = self.backend.themed_urls(file_name) 180 181 self.assertIsInstance(result, dict) 182 self.assertIn("light", result) 183 self.assertIn("dark", result) 184 185 # Check URLs contain the substituted theme 186 self.assertIn("logo-light.png", result["light"]) 187 self.assertIn("logo-dark.png", result["dark"]) 188 189 def test_themed_urls_multiple_theme_variables(self): 190 """Test themed_urls with multiple %(theme)s in path""" 191 file_name = "%(theme)s/logo-%(theme)s.svg" 192 result = self.backend.themed_urls(file_name) 193 194 self.assertIsInstance(result, dict) 195 self.assertIn("light/logo-light.svg", result["light"]) 196 self.assertIn("dark/logo-dark.svg", result["dark"])
Test FileBackend class
15 def setUp(self): 16 """Set up test fixtures""" 17 super().setUp() 18 self.backend = FileBackend(FileUsage.MEDIA)
Set up test fixtures
20 def test_allowed_usages(self): 21 """Test that FileBackend supports all usage types""" 22 self.assertEqual(self.backend.allowed_usages, list(FileUsage))
Test that FileBackend supports all usage types
24 def test_base_path(self): 25 """Test base_path property constructs correct path""" 26 base_path = self.backend.base_path 27 28 expected = Path(self.media_backend_path) / "media" / "public" 29 self.assertEqual(base_path, expected)
Test base_path property constructs correct path
31 def test_base_path_reports_usage(self): 32 """Test base_path with reports usage""" 33 backend = FileBackend(FileUsage.REPORTS) 34 base_path = backend.base_path 35 36 expected = Path(self.reports_backend_path) / "reports" / "public" 37 self.assertEqual(base_path, expected)
Test base_path with reports usage
39 def test_list_files_empty_directory(self): 40 """Test list_files returns empty when directory is empty""" 41 # Create the directory but keep it empty 42 self.backend.base_path.mkdir(parents=True, exist_ok=True) 43 44 files = list(self.backend.list_files()) 45 self.assertEqual(files, [])
Test list_files returns empty when directory is empty
47 def test_list_files_with_files(self): 48 """Test list_files returns all files in directory""" 49 base_path = self.backend.base_path 50 base_path.mkdir(parents=True, exist_ok=True) 51 52 # Create some test files 53 (base_path / "file1.txt").write_text("content1") 54 (base_path / "file2.png").write_text("content2") 55 (base_path / "subdir").mkdir() 56 (base_path / "subdir" / "file3.csv").write_text("content3") 57 58 files = sorted(list(self.backend.list_files())) 59 expected = sorted(["file1.txt", "file2.png", "subdir/file3.csv"]) 60 self.assertEqual(files, expected)
Test list_files returns all files in directory
62 def test_list_files_nonexistent_directory(self): 63 """Test list_files returns empty when directory doesn't exist""" 64 files = list(self.backend.list_files()) 65 self.assertEqual(files, [])
Test list_files returns empty when directory doesn't exist
67 def test_save_file(self): 68 content = b"test file content" 69 file_name = "test.txt" 70 71 self.backend.save_file(file_name, content) 72 73 # Verify file was created 74 file_path = self.backend.base_path / file_name 75 self.assertTrue(file_path.exists()) 76 self.assertEqual(file_path.read_bytes(), content)
78 def test_save_file_creates_subdirectories(self): 79 """Test save_file creates parent directories as needed""" 80 content = b"nested file content" 81 file_name = "subdir1/subdir2/nested.txt" 82 83 self.backend.save_file(file_name, content) 84 85 # Verify file and directories were created 86 file_path = self.backend.base_path / file_name 87 self.assertTrue(file_path.exists()) 88 self.assertEqual(file_path.read_bytes(), content)
Test save_file creates parent directories as needed
90 def test_save_file_stream(self): 91 """Test save_file_stream context manager writes file correctly""" 92 content = b"streamed content" 93 file_name = "stream_test.txt" 94 95 with self.backend.save_file_stream(file_name) as f: 96 f.write(content) 97 98 # Verify file was created 99 file_path = self.backend.base_path / file_name 100 self.assertTrue(file_path.exists()) 101 self.assertEqual(file_path.read_bytes(), content)
Test save_file_stream context manager writes file correctly
103 def test_save_file_stream_creates_subdirectories(self): 104 """Test save_file_stream creates parent directories as needed""" 105 content = b"nested stream content" 106 file_name = "dir1/dir2/stream.bin" 107 108 with self.backend.save_file_stream(file_name) as f: 109 f.write(content) 110 111 # Verify file and directories were created 112 file_path = self.backend.base_path / file_name 113 self.assertTrue(file_path.exists()) 114 self.assertEqual(file_path.read_bytes(), content)
Test save_file_stream creates parent directories as needed
116 def test_delete_file(self): 117 """Test delete_file removes existing file""" 118 file_name = "to_delete.txt" 119 120 # Create file first 121 self.backend.save_file(file_name, b"content") 122 file_path = self.backend.base_path / file_name 123 self.assertTrue(file_path.exists()) 124 125 # Delete it 126 self.backend.delete_file(file_name) 127 self.assertFalse(file_path.exists())
Test delete_file removes existing file
129 def test_delete_file_nonexistent(self): 130 """Test delete_file handles nonexistent file gracefully""" 131 file_name = "does_not_exist.txt" 132 self.backend.delete_file(file_name)
Test delete_file handles nonexistent file gracefully
134 def test_file_url(self): 135 """Test file_url generates correct URL""" 136 file_name = "icon.png" 137 138 url = self.backend.file_url(file_name).split("?")[0] 139 expected = "/files/media/public/icon.png" 140 self.assertEqual(url, expected)
Test file_url generates correct URL
142 @CONFIG.patch("web.path", "/authentik/") 143 def test_file_url_with_prefix(self): 144 """Test file_url with web path prefix""" 145 file_name = "logo.svg" 146 147 url = self.backend.file_url(file_name).split("?")[0] 148 expected = "/authentik/files/media/public/logo.svg" 149 self.assertEqual(url, expected)
Test file_url with web path prefix
151 def test_file_url_nested_path(self): 152 """Test file_url with nested file path""" 153 file_name = "path/to/file.png" 154 155 url = self.backend.file_url(file_name).split("?")[0] 156 expected = "/files/media/public/path/to/file.png" 157 self.assertEqual(url, expected)
Test file_url with nested file path
159 def test_file_exists_true(self): 160 """Test file_exists returns True for existing file""" 161 file_name = "exists.txt" 162 self.backend.base_path.mkdir(parents=True, exist_ok=True) 163 (self.backend.base_path / file_name).touch() 164 self.assertTrue(self.backend.file_exists(file_name))
Test file_exists returns True for existing file
166 def test_file_exists_false(self): 167 """Test file_exists returns False for nonexistent file""" 168 self.assertFalse(self.backend.file_exists("does_not_exist.txt"))
Test file_exists returns False for nonexistent file
170 def test_themed_urls_without_theme_variable(self): 171 """Test themed_urls returns None when filename has no %(theme)s""" 172 file_name = "logo.png" 173 result = self.backend.themed_urls(file_name) 174 self.assertIsNone(result)
Test themed_urls returns None when filename has no %(theme)s
176 def test_themed_urls_with_theme_variable(self): 177 """Test themed_urls returns dict of URLs for each theme""" 178 file_name = "logo-%(theme)s.png" 179 result = self.backend.themed_urls(file_name) 180 181 self.assertIsInstance(result, dict) 182 self.assertIn("light", result) 183 self.assertIn("dark", result) 184 185 # Check URLs contain the substituted theme 186 self.assertIn("logo-light.png", result["light"]) 187 self.assertIn("logo-dark.png", result["dark"])
Test themed_urls returns dict of URLs for each theme
189 def test_themed_urls_multiple_theme_variables(self): 190 """Test themed_urls with multiple %(theme)s in path""" 191 file_name = "%(theme)s/logo-%(theme)s.svg" 192 result = self.backend.themed_urls(file_name) 193 194 self.assertIsInstance(result, dict) 195 self.assertIn("light/logo-light.svg", result["light"]) 196 self.assertIn("dark/logo-dark.svg", result["dark"])
Test themed_urls with multiple %(theme)s in path