authentik.admin.files.tests.test_api
test file api
1"""test file api""" 2 3from io import BytesIO 4 5from django.test import TestCase 6from django.urls import reverse 7 8from authentik.admin.files.manager import FileManager 9from authentik.admin.files.tests.utils import FileTestFileBackendMixin 10from authentik.admin.files.usage import FileUsage 11from authentik.core.tests.utils import create_test_admin_user 12from authentik.events.models import Event, EventAction 13 14 15class TestFileAPI(FileTestFileBackendMixin, TestCase): 16 """test file api""" 17 18 def setUp(self) -> None: 19 super().setUp() 20 self.user = create_test_admin_user() 21 self.client.force_login(self.user) 22 23 def test_upload_creates_event(self): 24 """Test that uploading a file creates a FILE_UPLOADED event""" 25 manager = FileManager(FileUsage.MEDIA) 26 file_content = b"test file content" 27 file_name = "test-upload.png" 28 29 # Upload file 30 response = self.client.post( 31 reverse("authentik_api:files"), 32 { 33 "file": BytesIO(file_content), 34 "name": file_name, 35 "usage": FileUsage.MEDIA.value, 36 }, 37 format="multipart", 38 ) 39 40 self.assertEqual(response.status_code, 200) 41 42 # Verify event was created 43 event = Event.objects.filter(action=EventAction.MODEL_CREATED).first() 44 45 self.assertIsNotNone(event) 46 assert event is not None # nosec 47 self.assertEqual(event.context["model"]["name"], file_name) 48 self.assertEqual(event.context["model"]["usage"], FileUsage.MEDIA.value) 49 self.assertEqual(event.context["model"]["mime_type"], "image/png") 50 51 # Verify user is captured 52 self.assertEqual(event.user["username"], self.user.username) 53 self.assertEqual(event.user["pk"], self.user.pk) 54 55 manager.delete_file(file_name) 56 57 def test_delete_creates_event(self): 58 """Test that deleting a file creates an event""" 59 manager = FileManager(FileUsage.MEDIA) 60 file_name = "test-delete.png" 61 manager.save_file(file_name, b"test content") 62 63 # Delete file 64 response = self.client.delete( 65 reverse( 66 "authentik_api:files", 67 query={ 68 "name": file_name, 69 "usage": FileUsage.MEDIA.value, 70 }, 71 ) 72 ) 73 74 self.assertEqual(response.status_code, 200) 75 76 # Verify event was created 77 event = Event.objects.filter(action=EventAction.MODEL_DELETED).first() 78 79 self.assertIsNotNone(event) 80 assert event is not None # nosec 81 self.assertEqual(event.context["model"]["name"], file_name) 82 self.assertEqual(event.context["model"]["usage"], FileUsage.MEDIA.value) 83 84 # Verify user is captured 85 self.assertEqual(event.user["username"], self.user.username) 86 self.assertEqual(event.user["pk"], self.user.pk) 87 88 def test_list_files_basic(self): 89 """Test listing files with default parameters""" 90 response = self.client.get(reverse("authentik_api:files")) 91 92 self.assertEqual(response.status_code, 200) 93 self.assertIn( 94 { 95 "name": "/static/authentik/sources/ldap.png", 96 "url": "http://testserver/static/authentik/sources/ldap.png", 97 "mime_type": "image/png", 98 "themed_urls": None, 99 }, 100 response.data, 101 ) 102 103 def test_list_files_invalid_usage(self): 104 """Test listing files with invalid usage parameter""" 105 response = self.client.get( 106 reverse( 107 "authentik_api:files", 108 query={ 109 "usage": "invalid", 110 }, 111 ) 112 ) 113 114 self.assertEqual(response.status_code, 400) 115 self.assertIn("not a valid choice", str(response.data)) 116 117 def test_list_files_with_search(self): 118 """Test listing files with search query""" 119 response = self.client.get( 120 reverse( 121 "authentik_api:files", 122 query={ 123 "search": "ldap.png", 124 }, 125 ) 126 ) 127 128 self.assertEqual(response.status_code, 200) 129 self.assertIn( 130 { 131 "name": "/static/authentik/sources/ldap.png", 132 "url": "http://testserver/static/authentik/sources/ldap.png", 133 "mime_type": "image/png", 134 "themed_urls": None, 135 }, 136 response.data, 137 ) 138 139 def test_list_files_with_manageable_only(self): 140 """Test listing files with omit parameter""" 141 response = self.client.get( 142 reverse( 143 "authentik_api:files", 144 query={ 145 "manageableOnly": "true", 146 }, 147 ) 148 ) 149 150 self.assertEqual(response.status_code, 200) 151 self.assertNotIn( 152 { 153 "name": "/static/dist/assets/images/flow_background.jpg", 154 "mime_type": "image/jpeg", 155 }, 156 response.data, 157 ) 158 159 def test_upload_file_with_custom_path(self): 160 """Test uploading file with custom path""" 161 manager = FileManager(FileUsage.MEDIA) 162 file_name = "custom/test" 163 file_content = b"test content" 164 response = self.client.post( 165 reverse("authentik_api:files"), 166 { 167 "file": BytesIO(file_content), 168 "name": file_name, 169 "usage": FileUsage.MEDIA.value, 170 }, 171 format="multipart", 172 ) 173 174 self.assertEqual(response.status_code, 200) 175 self.assertTrue(manager.file_exists(file_name)) 176 manager.delete_file(file_name) 177 178 def test_upload_file_duplicate(self): 179 """Test uploading file that already exists""" 180 manager = FileManager(FileUsage.MEDIA) 181 file_name = "test-file.png" 182 file_content = b"test content" 183 manager.save_file(file_name, file_content) 184 response = self.client.post( 185 reverse("authentik_api:files"), 186 { 187 "file": BytesIO(file_content), 188 "name": file_name, 189 }, 190 format="multipart", 191 ) 192 193 self.assertEqual(response.status_code, 400) 194 self.assertIn("already exists", str(response.data)) 195 manager.delete_file(file_name) 196 197 def test_delete_without_name_parameter(self): 198 """Test delete without name parameter""" 199 response = self.client.delete(reverse("authentik_api:files")) 200 201 self.assertEqual(response.status_code, 400) 202 self.assertIn("field is required", str(response.data)) 203 204 def test_list_files_includes_themed_urls_none(self): 205 """Test listing files includes themed_urls as None for non-themed files""" 206 manager = FileManager(FileUsage.MEDIA) 207 file_name = "test-no-theme.png" 208 manager.save_file(file_name, b"test content") 209 210 response = self.client.get( 211 reverse("authentik_api:files", query={"search": file_name, "manageableOnly": "true"}) 212 ) 213 214 self.assertEqual(response.status_code, 200) 215 file_entry = next((f for f in response.data if f["name"] == file_name), None) 216 self.assertIsNotNone(file_entry) 217 self.assertIn("themed_urls", file_entry) 218 self.assertIsNone(file_entry["themed_urls"]) 219 220 manager.delete_file(file_name) 221 222 def test_list_files_includes_themed_urls_dict(self): 223 """Test listing files includes themed_urls as dict for themed files""" 224 manager = FileManager(FileUsage.MEDIA) 225 file_name = "logo-%(theme)s.svg" 226 manager.save_file("logo-light.svg", b"<svg>light</svg>") 227 manager.save_file("logo-dark.svg", b"<svg>dark</svg>") 228 manager.save_file(file_name, b"<svg>placeholder</svg>") 229 230 response = self.client.get( 231 reverse("authentik_api:files", query={"search": "%(theme)s", "manageableOnly": "true"}) 232 ) 233 234 self.assertEqual(response.status_code, 200) 235 file_entry = next((f for f in response.data if f["name"] == file_name), None) 236 self.assertIsNotNone(file_entry) 237 self.assertIn("themed_urls", file_entry) 238 self.assertIsInstance(file_entry["themed_urls"], dict) 239 self.assertIn("light", file_entry["themed_urls"]) 240 self.assertIn("dark", file_entry["themed_urls"]) 241 242 manager.delete_file(file_name) 243 manager.delete_file("logo-light.svg") 244 manager.delete_file("logo-dark.svg") 245 246 def test_upload_file_with_theme_variable(self): 247 """Test uploading file with %(theme)s in name""" 248 manager = FileManager(FileUsage.MEDIA) 249 file_name = "brand-logo-%(theme)s.svg" 250 file_content = b"<svg></svg>" 251 252 response = self.client.post( 253 reverse("authentik_api:files"), 254 { 255 "file": BytesIO(file_content), 256 "name": file_name, 257 "usage": FileUsage.MEDIA.value, 258 }, 259 format="multipart", 260 ) 261 262 self.assertEqual(response.status_code, 200) 263 self.assertTrue(manager.file_exists(file_name)) 264 manager.delete_file(file_name)
class
TestFileAPI(authentik.admin.files.tests.utils.FileTestFileBackendMixin, django.test.testcases.TestCase):
16class TestFileAPI(FileTestFileBackendMixin, TestCase): 17 """test file api""" 18 19 def setUp(self) -> None: 20 super().setUp() 21 self.user = create_test_admin_user() 22 self.client.force_login(self.user) 23 24 def test_upload_creates_event(self): 25 """Test that uploading a file creates a FILE_UPLOADED event""" 26 manager = FileManager(FileUsage.MEDIA) 27 file_content = b"test file content" 28 file_name = "test-upload.png" 29 30 # Upload file 31 response = self.client.post( 32 reverse("authentik_api:files"), 33 { 34 "file": BytesIO(file_content), 35 "name": file_name, 36 "usage": FileUsage.MEDIA.value, 37 }, 38 format="multipart", 39 ) 40 41 self.assertEqual(response.status_code, 200) 42 43 # Verify event was created 44 event = Event.objects.filter(action=EventAction.MODEL_CREATED).first() 45 46 self.assertIsNotNone(event) 47 assert event is not None # nosec 48 self.assertEqual(event.context["model"]["name"], file_name) 49 self.assertEqual(event.context["model"]["usage"], FileUsage.MEDIA.value) 50 self.assertEqual(event.context["model"]["mime_type"], "image/png") 51 52 # Verify user is captured 53 self.assertEqual(event.user["username"], self.user.username) 54 self.assertEqual(event.user["pk"], self.user.pk) 55 56 manager.delete_file(file_name) 57 58 def test_delete_creates_event(self): 59 """Test that deleting a file creates an event""" 60 manager = FileManager(FileUsage.MEDIA) 61 file_name = "test-delete.png" 62 manager.save_file(file_name, b"test content") 63 64 # Delete file 65 response = self.client.delete( 66 reverse( 67 "authentik_api:files", 68 query={ 69 "name": file_name, 70 "usage": FileUsage.MEDIA.value, 71 }, 72 ) 73 ) 74 75 self.assertEqual(response.status_code, 200) 76 77 # Verify event was created 78 event = Event.objects.filter(action=EventAction.MODEL_DELETED).first() 79 80 self.assertIsNotNone(event) 81 assert event is not None # nosec 82 self.assertEqual(event.context["model"]["name"], file_name) 83 self.assertEqual(event.context["model"]["usage"], FileUsage.MEDIA.value) 84 85 # Verify user is captured 86 self.assertEqual(event.user["username"], self.user.username) 87 self.assertEqual(event.user["pk"], self.user.pk) 88 89 def test_list_files_basic(self): 90 """Test listing files with default parameters""" 91 response = self.client.get(reverse("authentik_api:files")) 92 93 self.assertEqual(response.status_code, 200) 94 self.assertIn( 95 { 96 "name": "/static/authentik/sources/ldap.png", 97 "url": "http://testserver/static/authentik/sources/ldap.png", 98 "mime_type": "image/png", 99 "themed_urls": None, 100 }, 101 response.data, 102 ) 103 104 def test_list_files_invalid_usage(self): 105 """Test listing files with invalid usage parameter""" 106 response = self.client.get( 107 reverse( 108 "authentik_api:files", 109 query={ 110 "usage": "invalid", 111 }, 112 ) 113 ) 114 115 self.assertEqual(response.status_code, 400) 116 self.assertIn("not a valid choice", str(response.data)) 117 118 def test_list_files_with_search(self): 119 """Test listing files with search query""" 120 response = self.client.get( 121 reverse( 122 "authentik_api:files", 123 query={ 124 "search": "ldap.png", 125 }, 126 ) 127 ) 128 129 self.assertEqual(response.status_code, 200) 130 self.assertIn( 131 { 132 "name": "/static/authentik/sources/ldap.png", 133 "url": "http://testserver/static/authentik/sources/ldap.png", 134 "mime_type": "image/png", 135 "themed_urls": None, 136 }, 137 response.data, 138 ) 139 140 def test_list_files_with_manageable_only(self): 141 """Test listing files with omit parameter""" 142 response = self.client.get( 143 reverse( 144 "authentik_api:files", 145 query={ 146 "manageableOnly": "true", 147 }, 148 ) 149 ) 150 151 self.assertEqual(response.status_code, 200) 152 self.assertNotIn( 153 { 154 "name": "/static/dist/assets/images/flow_background.jpg", 155 "mime_type": "image/jpeg", 156 }, 157 response.data, 158 ) 159 160 def test_upload_file_with_custom_path(self): 161 """Test uploading file with custom path""" 162 manager = FileManager(FileUsage.MEDIA) 163 file_name = "custom/test" 164 file_content = b"test content" 165 response = self.client.post( 166 reverse("authentik_api:files"), 167 { 168 "file": BytesIO(file_content), 169 "name": file_name, 170 "usage": FileUsage.MEDIA.value, 171 }, 172 format="multipart", 173 ) 174 175 self.assertEqual(response.status_code, 200) 176 self.assertTrue(manager.file_exists(file_name)) 177 manager.delete_file(file_name) 178 179 def test_upload_file_duplicate(self): 180 """Test uploading file that already exists""" 181 manager = FileManager(FileUsage.MEDIA) 182 file_name = "test-file.png" 183 file_content = b"test content" 184 manager.save_file(file_name, file_content) 185 response = self.client.post( 186 reverse("authentik_api:files"), 187 { 188 "file": BytesIO(file_content), 189 "name": file_name, 190 }, 191 format="multipart", 192 ) 193 194 self.assertEqual(response.status_code, 400) 195 self.assertIn("already exists", str(response.data)) 196 manager.delete_file(file_name) 197 198 def test_delete_without_name_parameter(self): 199 """Test delete without name parameter""" 200 response = self.client.delete(reverse("authentik_api:files")) 201 202 self.assertEqual(response.status_code, 400) 203 self.assertIn("field is required", str(response.data)) 204 205 def test_list_files_includes_themed_urls_none(self): 206 """Test listing files includes themed_urls as None for non-themed files""" 207 manager = FileManager(FileUsage.MEDIA) 208 file_name = "test-no-theme.png" 209 manager.save_file(file_name, b"test content") 210 211 response = self.client.get( 212 reverse("authentik_api:files", query={"search": file_name, "manageableOnly": "true"}) 213 ) 214 215 self.assertEqual(response.status_code, 200) 216 file_entry = next((f for f in response.data if f["name"] == file_name), None) 217 self.assertIsNotNone(file_entry) 218 self.assertIn("themed_urls", file_entry) 219 self.assertIsNone(file_entry["themed_urls"]) 220 221 manager.delete_file(file_name) 222 223 def test_list_files_includes_themed_urls_dict(self): 224 """Test listing files includes themed_urls as dict for themed files""" 225 manager = FileManager(FileUsage.MEDIA) 226 file_name = "logo-%(theme)s.svg" 227 manager.save_file("logo-light.svg", b"<svg>light</svg>") 228 manager.save_file("logo-dark.svg", b"<svg>dark</svg>") 229 manager.save_file(file_name, b"<svg>placeholder</svg>") 230 231 response = self.client.get( 232 reverse("authentik_api:files", query={"search": "%(theme)s", "manageableOnly": "true"}) 233 ) 234 235 self.assertEqual(response.status_code, 200) 236 file_entry = next((f for f in response.data if f["name"] == file_name), None) 237 self.assertIsNotNone(file_entry) 238 self.assertIn("themed_urls", file_entry) 239 self.assertIsInstance(file_entry["themed_urls"], dict) 240 self.assertIn("light", file_entry["themed_urls"]) 241 self.assertIn("dark", file_entry["themed_urls"]) 242 243 manager.delete_file(file_name) 244 manager.delete_file("logo-light.svg") 245 manager.delete_file("logo-dark.svg") 246 247 def test_upload_file_with_theme_variable(self): 248 """Test uploading file with %(theme)s in name""" 249 manager = FileManager(FileUsage.MEDIA) 250 file_name = "brand-logo-%(theme)s.svg" 251 file_content = b"<svg></svg>" 252 253 response = self.client.post( 254 reverse("authentik_api:files"), 255 { 256 "file": BytesIO(file_content), 257 "name": file_name, 258 "usage": FileUsage.MEDIA.value, 259 }, 260 format="multipart", 261 ) 262 263 self.assertEqual(response.status_code, 200) 264 self.assertTrue(manager.file_exists(file_name)) 265 manager.delete_file(file_name)
test file api
def
setUp(self) -> None:
19 def setUp(self) -> None: 20 super().setUp() 21 self.user = create_test_admin_user() 22 self.client.force_login(self.user)
Hook method for setting up the test fixture before exercising it.
def
test_upload_creates_event(self):
24 def test_upload_creates_event(self): 25 """Test that uploading a file creates a FILE_UPLOADED event""" 26 manager = FileManager(FileUsage.MEDIA) 27 file_content = b"test file content" 28 file_name = "test-upload.png" 29 30 # Upload file 31 response = self.client.post( 32 reverse("authentik_api:files"), 33 { 34 "file": BytesIO(file_content), 35 "name": file_name, 36 "usage": FileUsage.MEDIA.value, 37 }, 38 format="multipart", 39 ) 40 41 self.assertEqual(response.status_code, 200) 42 43 # Verify event was created 44 event = Event.objects.filter(action=EventAction.MODEL_CREATED).first() 45 46 self.assertIsNotNone(event) 47 assert event is not None # nosec 48 self.assertEqual(event.context["model"]["name"], file_name) 49 self.assertEqual(event.context["model"]["usage"], FileUsage.MEDIA.value) 50 self.assertEqual(event.context["model"]["mime_type"], "image/png") 51 52 # Verify user is captured 53 self.assertEqual(event.user["username"], self.user.username) 54 self.assertEqual(event.user["pk"], self.user.pk) 55 56 manager.delete_file(file_name)
Test that uploading a file creates a FILE_UPLOADED event
def
test_delete_creates_event(self):
58 def test_delete_creates_event(self): 59 """Test that deleting a file creates an event""" 60 manager = FileManager(FileUsage.MEDIA) 61 file_name = "test-delete.png" 62 manager.save_file(file_name, b"test content") 63 64 # Delete file 65 response = self.client.delete( 66 reverse( 67 "authentik_api:files", 68 query={ 69 "name": file_name, 70 "usage": FileUsage.MEDIA.value, 71 }, 72 ) 73 ) 74 75 self.assertEqual(response.status_code, 200) 76 77 # Verify event was created 78 event = Event.objects.filter(action=EventAction.MODEL_DELETED).first() 79 80 self.assertIsNotNone(event) 81 assert event is not None # nosec 82 self.assertEqual(event.context["model"]["name"], file_name) 83 self.assertEqual(event.context["model"]["usage"], FileUsage.MEDIA.value) 84 85 # Verify user is captured 86 self.assertEqual(event.user["username"], self.user.username) 87 self.assertEqual(event.user["pk"], self.user.pk)
Test that deleting a file creates an event
def
test_list_files_basic(self):
89 def test_list_files_basic(self): 90 """Test listing files with default parameters""" 91 response = self.client.get(reverse("authentik_api:files")) 92 93 self.assertEqual(response.status_code, 200) 94 self.assertIn( 95 { 96 "name": "/static/authentik/sources/ldap.png", 97 "url": "http://testserver/static/authentik/sources/ldap.png", 98 "mime_type": "image/png", 99 "themed_urls": None, 100 }, 101 response.data, 102 )
Test listing files with default parameters
def
test_list_files_invalid_usage(self):
104 def test_list_files_invalid_usage(self): 105 """Test listing files with invalid usage parameter""" 106 response = self.client.get( 107 reverse( 108 "authentik_api:files", 109 query={ 110 "usage": "invalid", 111 }, 112 ) 113 ) 114 115 self.assertEqual(response.status_code, 400) 116 self.assertIn("not a valid choice", str(response.data))
Test listing files with invalid usage parameter
def
test_list_files_with_search(self):
118 def test_list_files_with_search(self): 119 """Test listing files with search query""" 120 response = self.client.get( 121 reverse( 122 "authentik_api:files", 123 query={ 124 "search": "ldap.png", 125 }, 126 ) 127 ) 128 129 self.assertEqual(response.status_code, 200) 130 self.assertIn( 131 { 132 "name": "/static/authentik/sources/ldap.png", 133 "url": "http://testserver/static/authentik/sources/ldap.png", 134 "mime_type": "image/png", 135 "themed_urls": None, 136 }, 137 response.data, 138 )
Test listing files with search query
def
test_list_files_with_manageable_only(self):
140 def test_list_files_with_manageable_only(self): 141 """Test listing files with omit parameter""" 142 response = self.client.get( 143 reverse( 144 "authentik_api:files", 145 query={ 146 "manageableOnly": "true", 147 }, 148 ) 149 ) 150 151 self.assertEqual(response.status_code, 200) 152 self.assertNotIn( 153 { 154 "name": "/static/dist/assets/images/flow_background.jpg", 155 "mime_type": "image/jpeg", 156 }, 157 response.data, 158 )
Test listing files with omit parameter
def
test_upload_file_with_custom_path(self):
160 def test_upload_file_with_custom_path(self): 161 """Test uploading file with custom path""" 162 manager = FileManager(FileUsage.MEDIA) 163 file_name = "custom/test" 164 file_content = b"test content" 165 response = self.client.post( 166 reverse("authentik_api:files"), 167 { 168 "file": BytesIO(file_content), 169 "name": file_name, 170 "usage": FileUsage.MEDIA.value, 171 }, 172 format="multipart", 173 ) 174 175 self.assertEqual(response.status_code, 200) 176 self.assertTrue(manager.file_exists(file_name)) 177 manager.delete_file(file_name)
Test uploading file with custom path
def
test_upload_file_duplicate(self):
179 def test_upload_file_duplicate(self): 180 """Test uploading file that already exists""" 181 manager = FileManager(FileUsage.MEDIA) 182 file_name = "test-file.png" 183 file_content = b"test content" 184 manager.save_file(file_name, file_content) 185 response = self.client.post( 186 reverse("authentik_api:files"), 187 { 188 "file": BytesIO(file_content), 189 "name": file_name, 190 }, 191 format="multipart", 192 ) 193 194 self.assertEqual(response.status_code, 400) 195 self.assertIn("already exists", str(response.data)) 196 manager.delete_file(file_name)
Test uploading file that already exists
def
test_delete_without_name_parameter(self):
198 def test_delete_without_name_parameter(self): 199 """Test delete without name parameter""" 200 response = self.client.delete(reverse("authentik_api:files")) 201 202 self.assertEqual(response.status_code, 400) 203 self.assertIn("field is required", str(response.data))
Test delete without name parameter
def
test_list_files_includes_themed_urls_none(self):
205 def test_list_files_includes_themed_urls_none(self): 206 """Test listing files includes themed_urls as None for non-themed files""" 207 manager = FileManager(FileUsage.MEDIA) 208 file_name = "test-no-theme.png" 209 manager.save_file(file_name, b"test content") 210 211 response = self.client.get( 212 reverse("authentik_api:files", query={"search": file_name, "manageableOnly": "true"}) 213 ) 214 215 self.assertEqual(response.status_code, 200) 216 file_entry = next((f for f in response.data if f["name"] == file_name), None) 217 self.assertIsNotNone(file_entry) 218 self.assertIn("themed_urls", file_entry) 219 self.assertIsNone(file_entry["themed_urls"]) 220 221 manager.delete_file(file_name)
Test listing files includes themed_urls as None for non-themed files
def
test_list_files_includes_themed_urls_dict(self):
223 def test_list_files_includes_themed_urls_dict(self): 224 """Test listing files includes themed_urls as dict for themed files""" 225 manager = FileManager(FileUsage.MEDIA) 226 file_name = "logo-%(theme)s.svg" 227 manager.save_file("logo-light.svg", b"<svg>light</svg>") 228 manager.save_file("logo-dark.svg", b"<svg>dark</svg>") 229 manager.save_file(file_name, b"<svg>placeholder</svg>") 230 231 response = self.client.get( 232 reverse("authentik_api:files", query={"search": "%(theme)s", "manageableOnly": "true"}) 233 ) 234 235 self.assertEqual(response.status_code, 200) 236 file_entry = next((f for f in response.data if f["name"] == file_name), None) 237 self.assertIsNotNone(file_entry) 238 self.assertIn("themed_urls", file_entry) 239 self.assertIsInstance(file_entry["themed_urls"], dict) 240 self.assertIn("light", file_entry["themed_urls"]) 241 self.assertIn("dark", file_entry["themed_urls"]) 242 243 manager.delete_file(file_name) 244 manager.delete_file("logo-light.svg") 245 manager.delete_file("logo-dark.svg")
Test listing files includes themed_urls as dict for themed files
def
test_upload_file_with_theme_variable(self):
247 def test_upload_file_with_theme_variable(self): 248 """Test uploading file with %(theme)s in name""" 249 manager = FileManager(FileUsage.MEDIA) 250 file_name = "brand-logo-%(theme)s.svg" 251 file_content = b"<svg></svg>" 252 253 response = self.client.post( 254 reverse("authentik_api:files"), 255 { 256 "file": BytesIO(file_content), 257 "name": file_name, 258 "usage": FileUsage.MEDIA.value, 259 }, 260 format="multipart", 261 ) 262 263 self.assertEqual(response.status_code, 200) 264 self.assertTrue(manager.file_exists(file_name)) 265 manager.delete_file(file_name)
Test uploading file with %(theme)s in name