diff --git a/sage_validation/accounts/models.py b/sage_validation/accounts/models.py
new file mode 100644
index 0000000000000000000000000000000000000000..bb02ea1bc40b0b978575da3501870f602039c4ac
--- /dev/null
+++ b/sage_validation/accounts/models.py
@@ -0,0 +1,42 @@
+import hashlib
+
+from django.contrib.auth.models import User
+from django.db import models
+
+
+class UserActivityLog(models.Model):
+    """Model to log user activities."""
+
+    ACTION_CHOICES = [
+        ("upload", "Upload"),
+        ("download", "Download"),
+    ]
+
+    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="activity_logs")
+    action = models.CharField(max_length=10, choices=ACTION_CHOICES)
+    name = models.CharField(max_length=255)
+    input_file_hash = models.CharField(max_length=64, blank=True, null=True)
+    output_file_hash = models.CharField(max_length=64, blank=True, null=True)
+    timestamp = models.DateTimeField(auto_now_add=True)
+
+    def __str__(self):
+        return f"{self.user.username} - {self.action} - {self.name} ({self.timestamp})"
+
+    @staticmethod
+    def generate_file_hash(file_obj: object) -> str:
+        """Generate SHA-256 hash for a file-like object."""
+        hasher = hashlib.sha256()
+
+        if hasattr(file_obj, "chunks"):
+            for chunk in file_obj.chunks():
+                hasher.update(chunk)
+        elif isinstance(file_obj, str):
+            hasher.update(file_obj.encode("utf-8"))
+
+        elif isinstance(file_obj, list):
+            hasher.update(str(file_obj).encode("utf-8"))
+
+        else:
+            raise TypeError("generate_file_hash() expected a file, BytesIO, string, or list.")
+
+        return hasher.hexdigest()