diff --git a/poetry.lock b/poetry.lock
index 7231e2e94faac3c750d9104c437fe30a24dc6447..93585f3c291af9f8b9df03390c73f1085fa847f5 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand.
 
 [[package]]
 name = "asgiref"
@@ -240,18 +240,18 @@ bcrypt = ["bcrypt"]
 
 [[package]]
 name = "django-auth-ldap"
-version = "4.1.0"
+version = "4.2.0"
 description = "Django LDAP authentication backend."
 category = "main"
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "django-auth-ldap-4.1.0.tar.gz", hash = "sha256:77f749d3b17807ce8eb56a9c9c8e5746ff316567f81d5ba613495d9c7495a949"},
-    {file = "django_auth_ldap-4.1.0-py3-none-any.whl", hash = "sha256:68870e7921e84b1a9867e268a9c8a3e573e8a0d95ea08bcf31be178f5826ff36"},
+    {file = "django-auth-ldap-4.2.0.tar.gz", hash = "sha256:aac71e65b0a8bdcfc5cd08b70997ee3cdc37786ffd5d975b7e2cfa47595d427f"},
+    {file = "django_auth_ldap-4.2.0-py3-none-any.whl", hash = "sha256:3eb0d963cd6e8225d0a588a828ce35a5c5c3309f7ad56dc5d68f8c807ddeaeff"},
 ]
 
 [package.dependencies]
-Django = ">=2.2"
+Django = ">=3.2"
 python-ldap = ">=3.1"
 
 [[package]]
@@ -1249,14 +1249,14 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
 
 [[package]]
 name = "setuptools"
-version = "67.6.0"
+version = "67.6.1"
 description = "Easily download, build, install, upgrade, and uninstall Python packages"
 category = "main"
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "setuptools-67.6.0-py3-none-any.whl", hash = "sha256:b78aaa36f6b90a074c1fa651168723acbf45d14cb1196b6f02c0fd07f17623b2"},
-    {file = "setuptools-67.6.0.tar.gz", hash = "sha256:2ee892cd5f29f3373097f5a814697e397cf3ce313616df0af11231e2ad118077"},
+    {file = "setuptools-67.6.1-py3-none-any.whl", hash = "sha256:e728ca814a823bf7bf60162daf9db95b93d532948c4c0bea762ce62f60189078"},
+    {file = "setuptools-67.6.1.tar.gz", hash = "sha256:257de92a9d50a60b8e22abfcbb771571fde0dbf3ec234463212027a4eeecbe9a"},
 ]
 
 [package.extras]
diff --git a/program/models.py b/program/models.py
index fa277abc328f3a9d4c627d21633a2331668f32c6..4b9da2ac136760e48eed34b9fcc02a06f1bee2eb 100644
--- a/program/models.py
+++ b/program/models.py
@@ -174,6 +174,36 @@ class Language(models.Model):
         return self.name
 
 
+class Image(models.Model):
+    alt_text = models.TextField(blank=True, null=True)
+    credits = models.TextField(blank=True, null=True)
+    height = models.PositiveIntegerField(blank=True, null=True, editable=False)
+    image = VersatileImageField(
+        blank=True,
+        height_field="height",
+        null=True,
+        ppoi_field="ppoi",
+        upload_to="images",
+        width_field="width",
+    )
+    owner = models.CharField(max_length=150)
+    ppoi = PPOIField()
+    width = models.PositiveIntegerField(blank=True, null=True, editable=False)
+
+    def save(self, *args, **kwargs):
+        super().save(*args, **kwargs)
+
+        if self.image.name and THUMBNAIL_SIZES:
+            for size in THUMBNAIL_SIZES:
+                self.image.thumbnail = self.image.crop[size].name
+
+    def delete(self, using=None, keep_parents=False):
+        self.image.delete_all_created_images()
+        self.image.delete(save=False)
+
+        super().delete(using, keep_parents)
+
+
 class Host(ModelWithImageFields, ModelWithCreatedUpdatedFields):
     name = models.CharField(max_length=128)
     is_active = models.BooleanField(default=True)