diff --git a/backend/account/migrations/0001_initial.py b/backend/account/migrations/0001_initial.py
new file mode 100644
index 0000000..3605242
--- /dev/null
+++ b/backend/account/migrations/0001_initial.py
@@ -0,0 +1,51 @@
+# Generated by Django 5.0 on 2024-09-15 16:11
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name="Profile",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("bio", models.CharField(blank=True, max_length=500)),
+                (
+                    "role",
+                    models.CharField(
+                        choices=[
+                            ("AUTHOR", "AUTHOR"),
+                            ("ADMIN", "ADMIN"),
+                            ("READER", "READER"),
+                        ],
+                        default="READER",
+                        max_length=10,
+                    ),
+                ),
+                (
+                    "user",
+                    models.OneToOneField(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        to=settings.AUTH_USER_MODEL,
+                    ),
+                ),
+            ],
+        ),
+    ]
diff --git a/backend/account/models.py b/backend/account/models.py
index d29314a..0ffb9a8 100644
--- a/backend/account/models.py
+++ b/backend/account/models.py
@@ -16,8 +16,8 @@ class Profile(models.Model):
         (READER, READER),
     )
     user = models.OneToOneField(User, on_delete=models.CASCADE)
-    bio = models.CharField(max_length=500, blank=True)
     role = models.CharField(max_length=10, choices=ROLE_CHOICES, default=READER)
+    bio = models.CharField(max_length=500, blank=True)
 
     def __str__(self):
         return self.user.username
diff --git a/backend/account/permissions.py b/backend/account/permissions.py
index 09be01f..77a1798 100644
--- a/backend/account/permissions.py
+++ b/backend/account/permissions.py
@@ -1,6 +1,7 @@
-from django.contrib.auth.models import User
 from rest_framework.permissions import SAFE_METHODS, BasePermission
 
+from .models import Profile
+
 
 class ReadOnly(BasePermission):
     def has_permission(self, request, view):
@@ -9,19 +10,27 @@ def has_permission(self, request, view):
 
 class IsReader(BasePermission):
     def has_permission(self, request, view):
-        return request.user.role == User.READER
+        return request.user.profile.role == Profile.READER
 
 
 class IsAuthor(BasePermission):
     def has_permission(self, request, view):
-        return request.user.role == User.AUTHOR
+        return request.user.profile.role == Profile.AUTHOR
+
+    def has_object_permission(self, request, view, obj):
+        return obj.author == request.user
 
 
 class IsAdmin(BasePermission):
     def has_permission(self, request, view):
-        return request.user.role == User.ADMIN
+        return request.user.profile.role == Profile.ADMIN
+
+
+class IsUser(BasePermission):
+    def has_object_permission(self, request, view, obj):
+        return obj == request.user
 
 
-class IsOwner(BasePermission):
+class IsOwnerOfObject(BasePermission):
     def has_object_permission(self, request, view, obj):
         return obj.user == request.user
diff --git a/backend/account/serializers.py b/backend/account/serializers.py
index b3ffc00..39e7265 100644
--- a/backend/account/serializers.py
+++ b/backend/account/serializers.py
@@ -2,7 +2,6 @@
 from django.contrib.auth.password_validation import validate_password
 from django.contrib.auth.validators import UnicodeUsernameValidator
 from rest_framework import serializers
-from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
 
 from .models import Profile
 
@@ -69,38 +68,29 @@ def create(self, validated_data):
 
 class ProfileSerializer(serializers.ModelSerializer):
     username = serializers.SerializerMethodField()
-    bio = serializers.CharField(max_length=500, read_only=True)
     role = serializers.CharField(max_length=10, read_only=True)
+    bio = serializers.CharField(max_length=500, allow_blank=True)
 
     class Meta:
         model = Profile
         fields = [
             "username",
-            "bio",
             "role",
+            "bio",
         ]
 
     def get_username(self, obj):
         return obj.user.username
 
-    def to_representation(self, instance):
-        representation = super().to_representation(instance)
-
-        # Conditionally remove the 'user' field when it's nested inside UserSerializer.
-        if "request" in self.context and isinstance(
-            self.context["request"].parser_context["view"], UserSerializer
-        ):
-            representation.pop("username", None)
-
 
 class UserSerializer(serializers.ModelSerializer):
     username = serializers.CharField(max_length=150)
-    email = serializers.EmailField()
-    first_name = serializers.CharField(max_length=150)
-    last_name = serializers.CharField(max_length=150)
+    email = serializers.EmailField(allow_blank=True)
+    first_name = serializers.CharField(max_length=150, allow_blank=True)
+    last_name = serializers.CharField(max_length=150, allow_blank=True)
     password1 = serializers.CharField(style={"input_type": "password"}, write_only=True)
     password2 = serializers.CharField(style={"input_type": "password"}, write_only=True)
-    profile_data = ProfileSerializer()
+    profile = ProfileSerializer()
 
     class Meta:
         model = User
@@ -111,7 +101,7 @@ class Meta:
             "last_name",
             "password1",
             "password2",
-            "profile_data",
+            "profile",
         ]
 
     def validate_username(self, username):
@@ -145,9 +135,7 @@ def validate(self, data):
         return data
 
     def update(self, instance, validated_data):
-        profile_data = validated_data.pop("profile_data")
-        profile = instance.profile
-
+        # Update User data.
         instance.username = validated_data.get("username", instance.username)
         instance.email = validated_data.get("email", instance.email)
         instance.irst_name = validated_data.get("first_name", instance.first_name)
@@ -159,18 +147,11 @@ def update(self, instance, validated_data):
 
         instance.save()
 
-        profile_data.bio = profile_data.get("bio")
-        if profile_data.bio:
+        # Update Profile data.
+        profile_data = validated_data.pop("profile", None)
+        profile = instance.profile
+        if profile_data:
+            profile.bio = profile_data.get("bio", profile.bio)
             profile.save()
 
         return instance
-
-
-class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
-    """A custom serializer that adds 'username' to the payload of a JWT token."""
-
-    @classmethod
-    def get_token(cls, user):
-        token = super().get_token(user)
-        token["username"] = user.username
-        return token
diff --git a/backend/account/views.py b/backend/account/views.py
index f391832..3bb4a59 100644
--- a/backend/account/views.py
+++ b/backend/account/views.py
@@ -7,16 +7,10 @@
 from rest_framework.response import Response
 from rest_framework.views import APIView
 from rest_framework_simplejwt.authentication import JWTAuthentication
-from rest_framework_simplejwt.views import TokenObtainPairView
 
 from .models import Profile
-from .permissions import IsAdmin, IsOwner, ReadOnly
-from .serializers import (
-    CustomTokenObtainPairSerializer,
-    ProfileSerializer,
-    UserRegisterSerializer,
-    UserSerializer,
-)
+from .permissions import IsAdmin, IsUser, ReadOnly
+from .serializers import ProfileSerializer, UserRegisterSerializer, UserSerializer
 
 
 class UserRegisterView(APIView):
@@ -55,7 +49,7 @@ def post(self, request, *args, **kwargs):
 
 class UserView(APIView):
     authentication_classes = (JWTAuthentication,)
-    permission_classes = (ReadOnly | (IsAuthenticated & (IsOwner | IsAdmin)),)
+    permission_classes = (ReadOnly | (IsAuthenticated & (IsUser | IsAdmin)),)
 
     @swagger_auto_schema(
         tags=["user"],
@@ -72,17 +66,18 @@ class UserView(APIView):
     )
     def get(self, request, username, *args, **kwargs):
         """Get a user's information."""
-        user = get_object_or_404(Profile, username=username)
+        user = get_object_or_404(User, username=username)
+        profile = user.profile
 
         if request.user.is_authenticated:
-            if request.user == user or request.user.role == Profile.ADMIN:
+            if request.user == user or request.user.profile.role == Profile.ADMIN:
                 serializer = UserSerializer(user)
             else:
                 # Use the public serializer for users that do not have the admin role.
-                serializer = ProfileSerializer(user)
+                serializer = ProfileSerializer(profile)
         else:
             # Use the public serializer for non-authenticated users.
-            serializer = ProfileSerializer(user)
+            serializer = ProfileSerializer(profile)
 
         return Response(serializer.data, status=status.HTTP_200_OK)
 
@@ -104,6 +99,8 @@ def get(self, request, username, *args, **kwargs):
     def put(self, request, username, *args, **kwargs):
         """Update a user's information."""
         user = get_object_or_404(User, username=username)
+        self.check_object_permissions(request, user)
+
         serializer = UserSerializer(user, data=request.data, partial=True)
         if serializer.is_valid():
             serializer.save()
@@ -127,11 +124,7 @@ def put(self, request, username, *args, **kwargs):
     def delete(self, request, username, *args, **kwargs):
         """Delete a user."""
         user = get_object_or_404(User, username=username)
+        self.check_object_permissions(request, user)
+
         user.delete()
         return Response({"detail": "User deleted successfully."}, status=status.HTTP_200_OK)
-
-
-class CustomTokenObtainPairView(TokenObtainPairView):
-    """A custom view for user authentication using JWT."""
-
-    serializer_class = CustomTokenObtainPairSerializer
diff --git a/backend/blog/urls.py b/backend/blog/urls.py
index d749409..f856c89 100644
--- a/backend/blog/urls.py
+++ b/backend/blog/urls.py
@@ -1,12 +1,10 @@
-from account.views import CustomTokenObtainPairView
 from django.urls import include, path
 from rest_framework_simplejwt.views import TokenBlacklistView, TokenObtainPairView, TokenRefreshView
 
 app_name = "blog"
 urlpatterns = [
     path("users/", include("account.urls")),
-    path("token/", CustomTokenObtainPairView.as_view(), name="token_obtain_pair"),
-    path("token-test/", TokenObtainPairView.as_view(), name="token_obtain_pair_test"),
+    path("token/", TokenObtainPairView.as_view(), name="token_obtain_pair"),
     path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
     path("token/blacklist/", TokenBlacklistView.as_view(), name="token_blacklist"),
     path("posts/", include("post.urls")),
diff --git a/backend/myproject/settings.py b/backend/myproject/settings.py
index ecee7fc..9569260 100644
--- a/backend/myproject/settings.py
+++ b/backend/myproject/settings.py
@@ -160,9 +160,8 @@
 ]
 
 
-# Settings to customize the behaviour of Simple JWT.
 SIMPLE_JWT = {
-    "ACCESS_TOKEN_LIFETIME": timedelta(minutes=5),
+    "ACCESS_TOKEN_LIFETIME": timedelta(minutes=60),
     "REFRESH_TOKEN_LIFETIME": timedelta(days=1),
     "ROTATE_REFRESH_TOKENS": True,
     "BLACKLIST_AFTER_ROTATION": True,
@@ -187,28 +186,8 @@
     "SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
     "SLIDING_TOKEN_LIFETIME": timedelta(minutes=5),
     "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
-    "TOKEN_OBTAIN_SERIALIZER": "account.serializers.CustomTokenObtainPairSerializer",
-    "TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer",
-    "TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer",
-    "TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer",
-    "SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer",
-    "SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer",
 }
 
-
-# Variables for verifying a new user's email address.
-VERIFICATION_EMAIL_TOKEN_EXPIRY_LIFE = 60 * 10  # 10 minutes.
-VERIFICATION_EMAIL_TOKEN_MAX_ATTEMPTS = 3
-
-# Variables for verifying a user's new email address.
-VERIFICATION_EMAIL_UPDATE_TOKEN_EXPIRY_LIFE = 60 * 10  # 10 minutes.
-
-# Variables allowing a user to reset their password.
-VERIFICATION_RESET_PASSWORD_TOKEN_EXPIRY_LIFE = 60 * 10  # 10 minutes.
-
-# Determines the period in which a user can verify their account during registration.
-MAX_TIME_TO_CONFIRM_EMAIL = 3 * 24 * 60 * 60  # 3 days.
-
 # Add username and password to Redis instance before deploying to production.
 CELERY_BROKER_URL = "redis://redis:6379/0"
 
diff --git a/backend/post/migrations/0001_initial.py b/backend/post/migrations/0001_initial.py
new file mode 100644
index 0000000..aca4e3d
--- /dev/null
+++ b/backend/post/migrations/0001_initial.py
@@ -0,0 +1,197 @@
+# Generated by Django 5.0 on 2024-09-15 16:11
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name="Category",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "name",
+                    models.CharField(
+                        choices=[("Technology", "Technology"), ("Life", "Life")],
+                        max_length=20,
+                        unique=True,
+                    ),
+                ),
+            ],
+            options={
+                "verbose_name_plural": "Categories",
+            },
+        ),
+        migrations.CreateModel(
+            name="Tag",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "name",
+                    models.CharField(
+                        choices=[
+                            ("Software Engineering", "Software Engineering"),
+                            ("Django", "Django"),
+                            ("Grit", "Grit"),
+                        ],
+                        max_length=20,
+                        unique=True,
+                    ),
+                ),
+            ],
+        ),
+        migrations.CreateModel(
+            name="Post",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("title", models.CharField(max_length=255, unique=True)),
+                ("subtitle", models.CharField(blank=True, max_length=255)),
+                ("slug", models.SlugField(blank=True, max_length=255, unique=True)),
+                ("body", models.TextField()),
+                ("meta_description", models.CharField(blank=True, max_length=150)),
+                ("date_created", models.DateTimeField(auto_now_add=True)),
+                ("date_modified", models.DateTimeField(auto_now=True)),
+                ("publish_date", models.DateTimeField(blank=True, null=True)),
+                ("published", models.BooleanField(default=False)),
+                (
+                    "author",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="posts",
+                        to=settings.AUTH_USER_MODEL,
+                    ),
+                ),
+                (
+                    "category",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.PROTECT, to="post.category"
+                    ),
+                ),
+                ("tags", models.ManyToManyField(blank=True, to="post.tag")),
+            ],
+            options={
+                "ordering": ["-publish_date"],
+            },
+        ),
+        migrations.CreateModel(
+            name="Comment",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("text", models.TextField()),
+                ("date_created", models.DateTimeField(auto_now_add=True)),
+                ("date_modified", models.DateTimeField(auto_now=True)),
+                ("is_deleted", models.BooleanField(default=False)),
+                (
+                    "parent_comment",
+                    models.ForeignKey(
+                        blank=True,
+                        null=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="replies",
+                        to="post.comment",
+                    ),
+                ),
+                (
+                    "user",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="comments",
+                        to=settings.AUTH_USER_MODEL,
+                    ),
+                ),
+                (
+                    "post",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE, to="post.post"
+                    ),
+                ),
+            ],
+            options={
+                "ordering": ["-date_created"],
+            },
+        ),
+        migrations.CreateModel(
+            name="Reaction",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "reaction_type",
+                    models.CharField(
+                        choices=[
+                            ("NEUTRAL", "NEUTRAL"),
+                            ("LIKE", "LIKE"),
+                            ("DISLIKE", "DISLIKE"),
+                        ],
+                        default="NEUTRAL",
+                        max_length=7,
+                    ),
+                ),
+                (
+                    "comment",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE, to="post.comment"
+                    ),
+                ),
+                (
+                    "user",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="reactions",
+                        to=settings.AUTH_USER_MODEL,
+                    ),
+                ),
+            ],
+            options={
+                "unique_together": {("user", "comment")},
+            },
+        ),
+    ]
diff --git a/backend/post/views.py b/backend/post/views.py
index 840bdc9..28bddd7 100644
--- a/backend/post/views.py
+++ b/backend/post/views.py
@@ -1,4 +1,4 @@
-from account.permissions import IsAdmin, IsAuthor, IsOwner, ReadOnly
+from account.permissions import IsAdmin, IsAuthor, IsOwnerOfObject, ReadOnly
 from django.utils import timezone
 from drf_yasg.utils import swagger_auto_schema
 from rest_framework import status
@@ -46,7 +46,6 @@ def post(self, request, *args, **kwargs):
 
         The user must be authenticated and be an author.
         """
-        # TODO: They must be creating a post under their account.
         serializer = PostWriteSerializer(data=request.data)
         if serializer.is_valid():
             serializer.save()
@@ -56,7 +55,7 @@ def post(self, request, *args, **kwargs):
 
 class PostDetailView(APIView):
     authentication_classes = (JWTAuthentication,)
-    permission_classes = (ReadOnly | (IsAuthenticated & (IsAdmin | (IsAuthor & IsOwner))),)
+    permission_classes = (ReadOnly | (IsAuthenticated & (IsAdmin | IsAuthor)),)
 
     @swagger_auto_schema(
         response={
@@ -85,6 +84,8 @@ def put(self, request, pk, *args, **kwargs):
         The user must be authenticated and must be an admin or the author of the post.
         """
         post = get_object_or_404(Post, pk=pk)
+        self.check_object_permissions(request, post)
+
         serializer = PostWriteSerializer(post, data=request.data, partial=True)
         if serializer.is_valid():
             serializer.save()
@@ -104,13 +105,15 @@ def delete(self, request, pk, *args, **kwargs):
         The user must be authenticated and must be an admin or the author of the post.
         """
         post = get_object_or_404(Post, pk=pk)
+        self.check_object_permissions(request, post)
+
         post.delete()
         return Response({"detail": "Post deleted successfully."}, status=status.HTTP_200_OK)
 
 
 class PublishPostView(APIView):
     authentication_classes = (JWTAuthentication,)
-    permission_classes = (IsAuthenticated & (IsAdmin | (IsAuthor & IsOwner)),)
+    permission_classes = (IsAuthenticated & (IsAdmin | IsAuthor),)
 
     @swagger_auto_schema(
         responses={
@@ -123,6 +126,8 @@ class PublishPostView(APIView):
     def post(self, request, pk, *args, **kwargs):
         """Publish an existing post."""
         post = get_object_or_404(Post, pk=pk)
+        self.check_object_permissions(request, post)
+
         if not post.published:
             post.published = True
             post.publish_date = timezone.now()
@@ -159,7 +164,7 @@ def post(self, request, pk, *args, **kwargs):
 
 class CommentDetailView(APIView):
     authentication_classes = (JWTAuthentication,)
-    permission_classes = (ReadOnly | (IsAuthenticated & IsOwner),)
+    permission_classes = (ReadOnly | (IsAuthenticated & IsOwnerOfObject),)
 
     def get(self, request, pk, *args, **kwargs):
         pass
@@ -177,6 +182,7 @@ def put(self, request, pk, *args, **kwargs):
     def delete(self, request, pk, *args, **kwargs):
         """Delete a comment."""
         comment = get_object_or_404(Comment, pk=pk)
+        self.check_object_permissions(request, comment)
 
         if comment.replies.exist():
             comment.soft_delete()