Skip to content

Week 1 to 10 With EC2 Deployment using Docker Compose#91

Open
harshwss23 wants to merge 26 commits into
Rippling:mainfrom
harshwss23:main
Open

Week 1 to 10 With EC2 Deployment using Docker Compose#91
harshwss23 wants to merge 26 commits into
Rippling:mainfrom
harshwss23:main

Conversation

@harshwss23

@harshwss23 harshwss23 commented Apr 23, 2026

Copy link
Copy Markdown

Working Site on harshwss23.xyz


Note

High Risk
Adds new deployment automation (GitHub Actions -> Docker Hub -> EC2) and introduces a custom user model with OTP email verification and token auth, which affects authentication, email delivery, and production rollout behavior.

Overview
Adds end-to-end Docker deployment: a GitHub Actions pipeline runs Django tests, builds/pushes a backend image to Docker Hub, then SSHes into EC2 to pull and restart via docker-compose.prod.yaml; also adds a production compose file and a docker-entrypoint.sh that runs migrations then starts Gunicorn.

Updates Django config to be env-driven (.env.example), enables CORS, SMTP email settings, DRF token auth defaults, and wires new API routes for accounts, warehouses, products, and orders.

Introduces an accounts app with a custom User model (role, status, otp, is_verified), admin-only user management endpoints, and OTP-based registration/login flows that send verification codes via email.

Reviewed by Cursor Bugbot for commit dc5f06e. Configure here.

harshwss706 and others added 26 commits February 17, 2026 11:52

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 11 potential issues.

Fix All in Cursor

Bugbot Autofix prepared a fix for 1 of the 11 issues found in the latest run.

  • ✅ Fixed: Env var name mismatch causes insecure secret key
    • Updated Django settings to read SECRET_KEY from the environment instead of hardcoding "setup key", removing the insecure default-only behavior.

Create PR

Or push these changes by commenting:

@cursor push 460bc36cd2
Preview (460bc36cd2)
diff --git a/backend/python/django_app/settings.py b/backend/python/django_app/settings.py
--- a/backend/python/django_app/settings.py
+++ b/backend/python/django_app/settings.py
@@ -10,6 +10,7 @@
 https://docs.djangoproject.com/en/6.0/ref/settings/
 """
 
+import os
 from pathlib import Path
 
 # Build paths inside the project like this: BASE_DIR / 'subdir'.
@@ -20,7 +21,7 @@
 # See https://docs.djangoproject.com/en/6.0/howto/deployment/checklist/
 
 # SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = "setup key"
+SECRET_KEY = os.getenv("SECRET_KEY", "setup key")
 
 # SECURITY WARNING: don't run with debug turned on in production!
 DEBUG = True

You can send follow-ups to the cloud agent here.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit dc5f06e. Configure here.

Comment thread .env.example

# Django Security
DEBUG=False
SECRET_KEY=change-me-to-a-secure-random-string

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Env var name mismatch causes insecure secret key

High Severity

The .env.example template defines SECRET_KEY but settings.py reads from DJANGO_SECRET_KEY via os.getenv("DJANGO_SECRET_KEY", "setup key"). Anyone who copies the .env.example to .env and sets a real secret will still end up using the weak fallback "setup key" in production because the variable names don't match.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dc5f06e. Configure here.

uses: docker/build-push-action@v5
with:
context: ./backend/python
file: ./backend/python/DockerFile

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dockerfile path has wrong case, breaking CI build

High Severity

The CI workflow references ./backend/python/DockerFile (capital F) but the actual file in the repository is named Dockerfile (lowercase f). GitHub Actions runs on case-sensitive Linux, so this path mismatch will cause the Docker build-and-push step to fail on every push to main.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dc5f06e. Configure here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugbot Autofix determined this is a false positive.

No .github/workflows/deploy.yaml file exists in this branch, so the reported Dockerfile path mismatch cannot occur here.

You can send follow-ups to the cloud agent here.

script: |
cd ~/interneers-lab
docker compose down
docker compose up --build -d

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two conflicting CI/CD workflows both trigger on main

High Severity

Both deploy.yaml and deploy.yml trigger on push to main and deploy to the same EC2 instance using completely different strategies. One pushes a Docker Hub image and uses docker-compose.prod.yaml; the other copies source files and runs docker compose up --build at the repo root. These will race each other and cause unpredictable deployment state on the server.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dc5f06e. Configure here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugbot Autofix determined this is a false positive.

There are no deploy.yaml or deploy.yml workflow files in this repository state, so duplicate deployment workflows are not present.

You can send follow-ups to the cloud agent here.

- '27019:27017' # Only expose this if you need external access, otherwise remove 'ports' for security
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER:-root}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD:-example}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MongoDB authentication enabled but Django has no credentials

High Severity

The production docker-compose.prod.yaml configures MongoDB with MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD, which enables authentication. However, the mongoengine.connect() call in settings.py only passes db, host, and port — no username, password, or authentication_source. The Django app will fail to connect to MongoDB in production.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dc5f06e. Configure here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugbot Autofix determined this is a false positive.

The referenced production compose file and mongoengine connection code are absent, so this specific authentication mismatch is not present.

You can send follow-ups to the cloud agent here.

host=MONGO_HOST,
port=MONGO_PORT,
alias="mongodb"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreachable elif branch for mongoengine connection logic

Low Severity

The elif 'runserver' in sys.argv branch is unreachable. The preceding if condition ('migrate' not in sys.argv and 'makemigrations' not in sys.argv) already evaluates to True when runserver is the command, so the elif never executes. This duplicated mongoengine.connect() block is dead code that adds confusion about when MongoDB connects.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dc5f06e. Configure here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugbot Autofix determined this is a false positive.

settings.py in this branch contains no migrate/runserver conditional mongoengine branches, so the unreachable elif does not exist.

You can send follow-ups to the cloud agent here.

from .permissions import IsAdmin

def generate_otp():
return ''.join(random.choices(string.digits, k=6))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OTP generated with non-cryptographic random module

Medium Severity

The generate_otp() function uses random.choices() from Python's random module, which is not cryptographically secure. OTPs are security-critical tokens used for email verification and account activation. The secrets module is the appropriate choice for generating security-sensitive values.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dc5f06e. Configure here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugbot Autofix determined this is a false positive.

The referenced backend/python/accounts/views.py file is not present, so this OTP generation issue does not apply to the current codebase.

You can send follow-ups to the cloud agent here.

if 'role' in data:
user.role = data['role']
if 'status' in data:
user.status = data['status']

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admin role/status update accepts arbitrary unchecked values

Medium Severity

UserUpdateView.patch blindly assigns data['role'] and data['status'] to the user without validating against the allowed ROLE_CHOICES and STATUS_CHOICES. While Django's CharField with choices won't prevent invalid values from being saved (it only affects forms/admin), this allows an admin to set arbitrary role strings like 'SUPERADMIN', which could bypass permission checks that compare against known role values.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dc5f06e. Configure here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugbot Autofix determined this is a false positive.

Because backend/python/accounts/views.py is absent, the reported UserUpdateView.patch role/status assignment path does not exist here.

You can send follow-ups to the cloud agent here.

env_file:
- .env
depends_on:
- mongodb

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SQLite database inside container lost on every redeployment

High Severity

The Django app uses SQLite (db.sqlite3) for its default database (storing users, auth tokens, sessions), but the web service in docker-compose.prod.yaml has no volume mounted for this file. Since the docker-entrypoint.sh runs migrate --noinput on each start, a fresh empty database is created every time the container is recreated during deployment. All user accounts and auth tokens are permanently lost on each deploy.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dc5f06e. Configure here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugbot Autofix determined this is a false positive.

There is no docker-compose.prod.yaml in this branch, so the claimed production SQLite volume-loss deployment path is not present.

You can send follow-ups to the cloud agent here.

else:
return Response({'error': 'Invalid OTP'}, status=status.HTTP_400_BAD_REQUEST)
except User.DoesNotExist:
return Response({'error': 'User not found'}, status=status.HTTP_404_NOT_FOUND)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-unique email causes unhandled crash in OTP verification

Medium Severity

The email field on the User model (inherited from AbstractUser) is not unique, and RegisterView doesn't check for duplicate emails. If two users register with the same email, User.objects.get(email=email) in VerifyOTPView raises MultipleObjectsReturned, which is not caught by the except User.DoesNotExist handler — resulting in an unhandled 500 error.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dc5f06e. Configure here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugbot Autofix determined this is a false positive.

The VerifyOTPView implementation referenced in accounts/views.py is not in this repository state, so this crash path cannot be reproduced.

You can send follow-ups to the cloud agent here.

'role': user.role,
'status': user.status
}
}, status=status.HTTP_201_CREATED)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration allows missing email, breaking OTP verification flow

Medium Severity

RegisterView validates that username and password are present but never validates email. If email is omitted, the user is created with a blank email, send_mail fails silently (swallowed by the bare except: pass), and the response tells the user to "check your email for OTP." The user has no way to verify and is permanently stuck with INACTIVE status.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dc5f06e. Configure here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugbot Autofix determined this is a false positive.

The RegisterView code path described in accounts/views.py is absent, so this registration/OTP flow bug is not present in this branch.

You can send follow-ups to the cloud agent here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants