From 5956beefe84ce2e78991900789cc96e50253797f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Oct 2025 16:36:00 +0000 Subject: [PATCH 1/5] Initial plan From 61cf4c2f9ab562de7d188475c8ec92854012849e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Oct 2025 16:41:15 +0000 Subject: [PATCH 2/5] Add PostgreSQL Docker setup and configuration files Co-authored-by: tymonaghan <33797221+tymonaghan@users.noreply.github.com> --- .env.example | 10 ++ README.md | 4 + SETUP.md | 218 ++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 23 +++++ package-lock.json | 18 ++++ package.json | 1 + server/db/database.js | 29 +++--- start.js | 1 + 8 files changed, 293 insertions(+), 11 deletions(-) create mode 100644 .env.example create mode 100644 SETUP.md create mode 100644 docker-compose.yml diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..ccb0ac7 --- /dev/null +++ b/.env.example @@ -0,0 +1,10 @@ +# Database Configuration +# For local development with Docker Compose +DATABASE_URL=postgres://studybuddy:studybuddy@localhost:5432/studybuddy + +# Server Port +PORT=3030 + +# Force database sync (drops all tables and recreates them) +# Set to true to reset the database on server start +FORCE_SYNC=false diff --git a/README.md b/README.md index 25475b9..493ba15 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,10 @@ Visit http://study-hero.herokuapp.com/ to use the app. You will need to create a **PLEASE NOTE** this is not a production product. Your account and its contents may be viewed, removed or altered without warning. DO NOT use this app for research that is not backed up nor to store any private or personally identifiable information. +## Local Development + +Want to run StudyBuddy locally or contribute to the project? See [SETUP.md](./SETUP.md) for detailed instructions on setting up your local development environment with PostgreSQL. + ## About Created by Tyler Monaghan ([GitHub](https://www.github.com/tymonaghan), [Portfolio](https://portfolio.tylermonaghan.dev)) for Async Week Project at Fullstack Academy diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 0000000..f0d94ce --- /dev/null +++ b/SETUP.md @@ -0,0 +1,218 @@ +# StudyBuddy Local Development Setup + +This guide will help you set up StudyBuddy for local development with a PostgreSQL database. + +## Prerequisites + +- [Node.js](https://nodejs.org/) (v14 or higher recommended) +- [Docker](https://www.docker.com/get-started) and Docker Compose (for local PostgreSQL) +- Git + +## Quick Start + +### 1. Clone the Repository + +```bash +git clone https://github.com/tymonaghan/studybuddy.git +cd studybuddy +``` + +### 2. Install Dependencies + +```bash +npm install +``` + +### 3. Set Up Environment Variables + +Copy the example environment file and customize it if needed: + +```bash +cp .env.example .env +``` + +The default `.env.example` is configured to work with the Docker Compose setup. If you're using a different PostgreSQL setup, update the `DATABASE_URL` in your `.env` file. + +### 4. Start PostgreSQL Database + +Using Docker Compose (recommended): + +```bash +docker-compose up -d +``` + +This will start a PostgreSQL container with: +- Database name: `studybuddy` +- Username: `studybuddy` +- Password: `studybuddy` +- Port: `5432` + +To stop the database: + +```bash +docker-compose down +``` + +To stop and remove all data: + +```bash +docker-compose down -v +``` + +### 5. Seed the Database + +Populate the database with initial test data: + +```bash +npm run seed +``` + +This will create: +- Test users (jimmy, ricky, bluey) +- Sample projects +- Sample sources + +### 6. Start the Application + +For development with hot reloading: + +```bash +npm run start:dev +``` + +This will: +- Start webpack in watch mode for frontend changes +- Start nodemon for backend changes +- The app will be available at `http://localhost:3030` + +For production mode: + +```bash +npm run build +npm start +``` + +## Database Management + +### Viewing Database Contents + +Connect to the PostgreSQL database: + +```bash +docker exec -it studybuddy-postgres psql -U studybuddy -d studybuddy +``` + +Useful PostgreSQL commands: +- `\dt` - List all tables +- `\d table_name` - Describe a table +- `SELECT * FROM "Users";` - View all users +- `\q` - Quit + +### Resetting the Database + +To completely reset the database: + +1. Set `FORCE_SYNC=true` in your `.env` file, OR +2. Run the seed script which forces a sync: + +```bash +npm run seed +``` + +### Manual PostgreSQL Setup + +If you prefer not to use Docker, install PostgreSQL locally: + +1. Install PostgreSQL for your operating system +2. Create a database named `studybuddy`: + ```bash + createdb studybuddy + ``` +3. Update your `.env` file with your local PostgreSQL connection string: + ``` + DATABASE_URL=postgres://your_username@localhost:5432/studybuddy + ``` + +## Testing + +Run tests with the test database: + +```bash +npm run test:dev +``` + +## Available Scripts + +- `npm run build` - Build the frontend bundle +- `npm start` - Start the server in production mode +- `npm run start:dev` - Start the server in development mode with hot reloading +- `npm run start-webpack` - Start only the webpack dev server +- `npm run seed` - Seed the database with test data +- `npm test` - Run tests with remote test database +- `npm run test:dev` - Run tests with local test database + +## Troubleshooting + +### Database Connection Issues + +If you see database connection errors: + +1. **Check if PostgreSQL is running:** + ```bash + docker ps + ``` + You should see the `studybuddy-postgres` container running. + +2. **Check database health:** + ```bash + docker-compose logs postgres + ``` + +3. **Verify connection string:** + Make sure your `.env` file has the correct `DATABASE_URL`. + +4. **Restart the database:** + ```bash + docker-compose restart + ``` + +### Port Already in Use + +If port 5432 or 3030 is already in use: + +- **For PostgreSQL (5432):** Stop other PostgreSQL instances or change the port in `docker-compose.yml` +- **For the app (3030):** Change the `PORT` variable in your `.env` file + +### Module Not Found Errors + +If you see module not found errors: + +```bash +rm -rf node_modules package-lock.json +npm install +``` + +## Project Structure + +``` +studybuddy/ +├── app/ # React frontend components +├── public/ # Static files +├── server/ # Express backend +│ ├── db/ # Database models and configuration +│ └── ... # API routes +├── tests/ # Test files +├── .env.example # Example environment variables +├── docker-compose.yml # Docker configuration for PostgreSQL +├── package.json # Node dependencies and scripts +└── start.js # Application entry point +``` + +## Next Steps + +- Create a user account at `http://localhost:3030` +- Create a project +- Add sources to your project +- Take notes on your sources + +For more information, see the main [README.md](./README.md). diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..af24a3f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,23 @@ +version: '3.8' + +services: + postgres: + image: postgres:14-alpine + container_name: studybuddy-postgres + restart: unless-stopped + environment: + POSTGRES_DB: studybuddy + POSTGRES_USER: studybuddy + POSTGRES_PASSWORD: studybuddy + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U studybuddy -d studybuddy"] + interval: 10s + timeout: 5s + retries: 5 + +volumes: + postgres_data: diff --git a/package-lock.json b/package-lock.json index 222029d..01753b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "body-parser": "^1.19.1", "bootstrap": "^5.1.3", "chalk": "^4.1.2", + "dotenv": "^17.2.3", "express": "^4.17.2", "jsonwebtoken": "^8.5.1", "nodemon": "^2.0.15", @@ -3667,6 +3668,18 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dottie": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", @@ -11428,6 +11441,11 @@ "is-obj": "^2.0.0" } }, + "dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==" + }, "dottie": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", diff --git a/package.json b/package.json index dfe7bb7..e6f86f9 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "body-parser": "^1.19.1", "bootstrap": "^5.1.3", "chalk": "^4.1.2", + "dotenv": "^17.2.3", "express": "^4.17.2", "jsonwebtoken": "^8.5.1", "nodemon": "^2.0.15", diff --git a/server/db/database.js b/server/db/database.js index ce16379..72dc57e 100644 --- a/server/db/database.js +++ b/server/db/database.js @@ -1,16 +1,23 @@ const Sequelize = require("sequelize"); -const db = new Sequelize( - process.env.DATABASE_URL || "postgres://localhost:5432/studybuddy", - { - dialectOptions: { - // this dialectOptions section is required for the heroku postgres add-on to connect - ssl: { - rejectUnauthorized: false, - }, +const databaseUrl = process.env.DATABASE_URL || "postgres://studybuddy:studybuddy@localhost:5432/studybuddy"; + +// Determine if we need SSL (for Heroku and other production databases) +const isProduction = process.env.NODE_ENV === 'production' || databaseUrl.includes('amazonaws.com'); + +const config = { + logging: false, +}; + +// Only add SSL config for production databases +if (isProduction) { + config.dialectOptions = { + ssl: { + rejectUnauthorized: false, }, - logging: false, - } -); + }; +} + +const db = new Sequelize(databaseUrl, config); module.exports = db; diff --git a/start.js b/start.js index 8cdddc0..383dc4d 100644 --- a/start.js +++ b/start.js @@ -1,3 +1,4 @@ +require('dotenv').config(); const { db } = require("./server/db"); const app = require("./server"); From 5c647e19e58a5f4dc9d2c776ff8419f6073b4e22 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Oct 2025 16:44:23 +0000 Subject: [PATCH 3/5] Remove obsolete version from docker-compose.yml Co-authored-by: tymonaghan <33797221+tymonaghan@users.noreply.github.com> --- docker-compose.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index af24a3f..276f218 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: postgres: image: postgres:14-alpine From 609a334566eda2f4d8c91893ee9d368c4aff1b21 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Oct 2025 16:46:41 +0000 Subject: [PATCH 4/5] Fix URL security check to properly validate hostname Co-authored-by: tymonaghan <33797221+tymonaghan@users.noreply.github.com> --- server/db/database.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/server/db/database.js b/server/db/database.js index 72dc57e..d6ce6a8 100644 --- a/server/db/database.js +++ b/server/db/database.js @@ -3,7 +3,16 @@ const Sequelize = require("sequelize"); const databaseUrl = process.env.DATABASE_URL || "postgres://studybuddy:studybuddy@localhost:5432/studybuddy"; // Determine if we need SSL (for Heroku and other production databases) -const isProduction = process.env.NODE_ENV === 'production' || databaseUrl.includes('amazonaws.com'); +// Parse the URL to properly check the hostname +let isProduction = process.env.NODE_ENV === 'production'; +try { + const url = new URL(databaseUrl); + // Check if hostname ends with amazonaws.com (matches RDS hosts) + isProduction = isProduction || url.hostname.endsWith('.amazonaws.com'); +} catch (err) { + // If URL parsing fails, fall back to NODE_ENV check only + console.warn('Warning: Unable to parse DATABASE_URL for SSL detection'); +} const config = { logging: false, From bbabaa4e1b8c21c4c609f886b1dad975adc3a048 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Oct 2025 16:49:06 +0000 Subject: [PATCH 5/5] Improve error logging in database URL parsing Co-authored-by: tymonaghan <33797221+tymonaghan@users.noreply.github.com> --- server/db/database.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/db/database.js b/server/db/database.js index d6ce6a8..d7ed93e 100644 --- a/server/db/database.js +++ b/server/db/database.js @@ -11,7 +11,7 @@ try { isProduction = isProduction || url.hostname.endsWith('.amazonaws.com'); } catch (err) { // If URL parsing fails, fall back to NODE_ENV check only - console.warn('Warning: Unable to parse DATABASE_URL for SSL detection'); + console.warn('Warning: Unable to parse DATABASE_URL for SSL detection:', err.message); } const config = {