Group Name: A
GitHub Repository: [https://github.com/BSCNRB344123/ADVANCED-DB-GROUP-A-2025]
Live API Documentation (when running): http://localhost:3000/api-docs
This project implements and optimizes a PostgreSQL database system for the UCI Wine Quality dataset. It demonstrates schema design (3NF), backend API development (Node.js/Express), interactive API documentation (Swagger), performance tuning via indexes, stored procedures, and triggers, and secure connectivity to a cloud-hosted database on Oracle Cloud Infrastructure (OCI).
- Database: PostgreSQL (v14.x deployed on OCI)
- Cloud Platform: Oracle Cloud Infrastructure (OCI)
- OCI Database with PostgreSQL (Managed Service)
- OCI Compute (for Bastion Host VM)
- OCI Virtual Cloud Network (VCN), Subnets, Security Lists/NSGs, Internet Gateway
- Backend: Node.js, Express.js
- Database Driver:
node-postgres(npm package:pg) - API Documentation: Swagger UI (
swagger-ui-express), Swagger JSDoc (swagger-jsdoc) - Data Handling:
csv-parser - Environment Variables:
dotenv - Connectivity: SSH Client (OpenSSH, Git Bash, or PuTTY) for tunneling
- Version Control: Git, GitHub
- Name: Wine Quality Dataset (Combined Red & White)
- Source: UC Irvine Machine Learning Repository
- Link: https://archive.ics.uci.edu/ml/datasets/wine+quality
- Files Required:
winequality-red.csv,winequality-white.csv(Must be placed in thedata/directory).
Ensure the following software is installed on the machine where you intend to run the setup and application:
- Node.js and npm: LTS version recommended (https://nodejs.org/). Verify installation by running
node -vandnpm -vin your terminal. - Git: Required for cloning the repository (https://git-scm.com/).
- PostgreSQL Client (
psql): Required for running.sqlsetup scripts. It's included with a full PostgreSQL installation or can often be installed separately. Verify by runningpsql --version. - SSH Client: Essential for creating the secure tunnel to the OCI Bastion host. Choose ONE of these options:
- Windows:
- OpenSSH Client (Recommended): Check if installed via Windows Settings -> Apps -> Optional features. If not, install it from there. Verify by opening Command Prompt or PowerShell and typing
ssh. - Git Bash: Included with Git for Windows installation. Provides a Linux-like environment with
ssh. - PuTTY: Download
putty.exeandputtygen.exefrom the official website (https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html). Requires key conversion to.ppkformat usingputtygen.exe.
- OpenSSH Client (Recommended): Check if installed via Windows Settings -> Apps -> Optional features. If not, install it from there. Verify by opening Command Prompt or PowerShell and typing
- macOS/Linux: The
sshcommand is typically built-in. Verify by opening a terminal and typingssh.
- Windows:
STEP 5.1: OCI Infrastructure Setup (Manual - OCI Console)
(These steps must be performed manually within your OCI account console before proceeding with local setup.)
- Provision OCI Database with PostgreSQL:
- Create a DB System using the managed PostgreSQL service.
- Place it in a Private Subnet within your chosen VCN.
- During creation, set and securely record the initial administrative password (usually for the
postgresuser). - Note the Database Name you intend to use (e.g.,
wine_quality). - Note the Private IP Endpoint (e.g.,
10.0.1.111) shown in the connection details. - Download the CA Certificate Bundle from the connection details. Based on your structure, you seem to have named this
CaCertificate-wine_quality.pub. Verify this is the CA bundle and not an SSH key. CA bundles are usually.pemfiles.
- Create Public Subnet (if needed):
- Ensure your VCN has a public subnet (uses a Route Table with a rule pointing
0.0.0.0/0to an Internet Gateway). Create one if necessary (e.g.,public-subnet-bastion).
- Ensure your VCN has a public subnet (uses a Route Table with a rule pointing
- Create Bastion Host (Compute Instance):
- Launch a small Compute Instance (e.g., Oracle Linux
VM.Standard.E2.1.Micro) in the Public Subnet. - Crucially: Ensure "Assign a public IPv4 address" is enabled during creation.
- Configure SSH keys: Generate a new key pair via OCI and SAVE BOTH the public and private key files securely, OR upload your existing public key. You MUST have the corresponding private key file locally.
- Note the Bastion's assigned Public IP Address, Private IP Address, and default OS Username (
opcfor Oracle Linux,ubuntufor Ubuntu).
- Launch a small Compute Instance (e.g., Oracle Linux
- Configure Network Security (Security Lists / NSGs):
- Rule 1 (SSH to Bastion): In the Security List/NSG associated with the Bastion's Public Subnet, add an Ingress Rule:
- Source:
Your Local Machine's Public IP Address/32(Find via "what is my IP address") - Protocol: TCP
- Destination Port:
22
- Source:
- Rule 2 (PG from Bastion to DB): In the Security List/NSG associated with the Database's Private Subnet (e.g.,
wine-quality-security-group), add an Ingress Rule:- Source:
Bastion's Private IP Address/32 - Protocol: TCP
- Destination Port:
5432(or your DB port)
- Source:
- Rule 1 (SSH to Bastion): In the Security List/NSG associated with the Bastion's Public Subnet, add an Ingress Rule:
STEP 5.2: Local Code Setup
- Clone Repository: Open your local terminal or Git Bash.
git clone [https://github.com/BSCNRB344123/ADVANCED-DB-GROUP-A-2025] cd [repository-folder-name] - Place Data Files: Ensure
winequality-red.csvandwinequality-white.csvare inside thedata/directory within the cloned project folder.
STEP 5.3: Establish SSH Tunnel
(This creates the secure connection path. Choose EITHER Command Line OR PuTTY.)
-
Open a dedicated Terminal/Command Prompt/Git Bash window for the tunnel. This window must remain open while you work with the database/API.
-
OPTION A: Command Line SSH (Recommended for Windows OpenSSH/Git Bash/macOS/Linux):
- Construct the command (replace all placeholders):
ssh -N -L <local_port>:<db_private_ip>:<db_port> <bastion_user>@<bastion_public_ip> -i "<path_to_your_private_key>"
<local_port>:5433(Recommended to avoid clashes)<db_private_ip>: The Private IP of your OCI Database (e.g.,10.0.1.111)<db_port>:5432<bastion_user>:opcorubuntu(Username for the Bastion VM OS)<bastion_public_ip>: Public IP address of your Bastion VM.<path_to_your_private_key>: Exact, full path to the SSH private key file you saved for the bastion. Use "Copy as path" in Windows Explorer or provide the full path. Ensure the path is correct and the file exists (fixNo such file or directoryerrors). Use quotes around the path if it contains spaces.
- Run the command. Accept the host key (
yes) if prompted on first connection. - Verification: The command should connect successfully and then appear to hang without returning to the command prompt. This indicates the tunnel is active. Leave this window running. Troubleshoot
Connection timed outerrors by checking the Bastion Public IP and the OCI Security Rule allowing SSH (Port 22) from your current local public IP. TroubleshootPermission deniederrors by verifying the key path, username, and key permissions (if on Linux/macOS).
- Construct the command (replace all placeholders):
-
OPTION B: PuTTY (Windows Graphical Client):
- Convert Key: If your private key isn't
.ppk, useputtygen.exe-> Load -> Select key -> Save private key (optionally add passphrase) -> Save as.ppk. - Run
putty.exe. - Session: Host Name=
<bastion_public_ip>, Port=22, Connection type=SSH. - Connection -> Data: Auto-login username=
<bastion_user>. - Connection -> SSH -> Auth -> Credentials: Browse and select your
.ppkprivate key file. - Connection -> SSH -> Tunnels:
- Source port:
5433(Recommended local port) - Destination:
<db_private_ip>:<db_port>(e.g.,10.0.1.111:5432) - Select
LocalandAuto. - Click
Add. Verify the rule appears in the list box.
- Source port:
- (Optional) Session: Save the session details for future use.
- Click
Open. Accept the host key if prompted. Enter key passphrase if you set one. - Verification: A PuTTY terminal window should open and log you into the bastion host. Keep this PuTTY window open to maintain the tunnel.
- Convert Key: If your private key isn't
STEP 5.4: Database Initialization
- Open a NEW local terminal window (different from the tunnel window).
- Ensure the SSH Tunnel from Step 5.3 is active.
-
Connect as Admin User:
psql -h localhost -p 5433 -U <Your_OCI_DB_Admin_User> -d postgres
- Replace
<Your_OCI_DB_Admin_User>(e.g.,postgres). - Enter the OCI DB Admin password set during DB System creation when prompted.
- Replace
-
Create Application Database (Inside
psql):CREATE DATABASE wine_quality;
- Verify success (
CREATE DATABASEmessage). Check if it already exists first with\lif needed.
- Verify success (
-
Exit
psql:\q
-
Apply Schema:
psql -h localhost -p 5433 -U <Your_OCI_DB_Admin_User> -d wine_quality -f database/schema.sql
- Enter admin password again. Verify no errors.
-
Apply Optimizations:
psql -h localhost -p 5433 -U <Your_OCI_DB_Admin_User> -d wine_quality -f database/optimizations.sql
- Enter admin password again. Verify no errors.
-
(Optional but Recommended) Create App User & Grant Privileges:
- Connect again as admin:
psql -h localhost -p 5433 -U <Your_OCI_DB_Admin_User> -d wine_quality - Inside
psql, run:-- Use a strong password for your app user! CREATE USER donnelly WITH PASSWORD 'donN1234#'; -- Example user/password from history GRANT CONNECT ON DATABASE wine_quality TO donnelly; GRANT USAGE ON SCHEMA public TO donnelly; GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE wines, wine_audit_log TO donnelly; GRANT USAGE, SELECT ON SEQUENCE wines_id_seq, wine_audit_log_log_id_seq TO donnelly; -- Add other grants if needed (e.g., EXECUTE on functions)
- Exit
psql:\q
- Connect again as admin:
STEP 5.5: Backend API Configuration
-
Navigate to Backend Folder:
cd wine-quality-backend # Navigate to your backend application folder
-
Edit
.envFile: Open the.envfile and carefully populate it. Use the dedicated app user/password (e.g.,donnelly) if you created one.# === EDIT THESE VALUES CAREFULLY === DB_USER=donnelly # The user the Node.js app connects as DB_PASSWORD=donN1234# # The password for DB_USER (NO QUOTES!) DB_DATABASE=wine_quality # The database created in Step 5.4 DB_HOST=localhost # Connect via the tunnel DB_PORT=5433 # The LOCAL port used in the tunnel command # SSL Settings - Required for OCI DB_SSL_ENABLED=true DB_SSL_REJECT_UNAUTHORIZED=false # NEEDED for tunnel connection to localhost DB_SSL_CA_CERT_FILENAME=CaCertificate-wine_quality.pub # MATCHES YOUR STRUCTURE - VERIFY IT'S A CA BUNDLE! # Server Port PORT=3000 # === END EDIT ===
- CRITICAL: Ensure
DB_PASSWORDhas no quotes around it. - CRITICAL: Ensure
DB_SSL_CA_CERT_FILENAMEmatches the exact name of the file in yourcerts/folder. Verify this file is the CA Bundle (usually.pem) and not an SSH key (.pub). - CRITICAL: Place the downloaded CA certificate file (e.g.,
CaCertificate-wine_quality.pubbased on your structure) inside thewine-quality-backend/certs/directory.
- CRITICAL: Ensure
-
Install Dependencies: While still in the
wine-quality-backenddirectory:npm install
STEP 5.6: Populate Database
- Navigate to Project Root:
cd .. - Ensure SSH Tunnel is Active.
- Run Population Script:
node database/populate.js
- Watch the console for success messages or errors (e.g., authentication failed, database doesn't exist - troubleshoot based on previous steps if errors occur).
- Ensure SSH Tunnel is Active (Terminal window from Step 5.3 is still open and connected/hanging).
- Open a NEW terminal window.
- Navigate to the backend directory:
cd wine-quality-backend - Start the Node.js server:
npm start
- Verification: Look for console output indicating the server is running and database connection pool is created without errors (especially check for password authentication or SSL errors). You should see output similar to:
Server running on port 3000 Attempting to connect to DB: wine_quality on localhost:5433 as donnelly Attempting to load CA certificate from: ...\certs\CaCertificate-wine_quality.pub SSL Configuration Enabled. rejectUnauthorized: false Database connection pool created. Client connected. SSL: Enabled Swagger docs available at http://localhost:3000/api-docs
- Swagger UI: Open a web browser and navigate to
http://localhost:3000/api-docs. - Use the UI to explore endpoints and click "Try it out" -> "Execute" to test API calls.
- Verify Connection: Successfully executing
GET /api/winesand receiving data confirms the connection to the OCI database is working through the tunnel.
- 3NF Schema: Database normalized to reduce redundancy (removed calculated
is_premiumcolumn). - Indexing: Indexes on
quality,alcohol,wine_typefor faster querying. - Stored Procedure:
calculate_average_qualityfor efficient server-side calculation. - Triggers: Automated
updated_attimestamp management and audit logging forqualitychanges. - Secure Cloud Connectivity: Use of OCI private database endpoint accessed via SSH Tunneling through a Bastion Host.
[repository-folder-name]/
├── .gitignore
├── data/ # CSV data files must be placed here
│ ├── winequality-red.csv
│ └── winequality-white.csv
├── database/ # Database scripts and tools
│ ├── optimizations.sql # Stored Procedures & Triggers
│ ├── populate.js # Data population script
│ └── schema.sql # 3NF Database schema SQL
├── wine-quality-backend/ # Node.js application
│ ├── certs/ # OCI CA certificate bundle must be placed here
│ │ └── CaCertificate-wine_quality.pub # Filename from your structure
│ ├── config/ # Configuration files
│ │ ├── db.config.js # Database connection pool setup
│ │ └── swagger.js # Swagger setup
│ ├── controllers/ # Request handling logic
│ │ └── wineController.js
│ ├── node_modules/ # NPM packages (generated)
│ ├── routes/ # API endpoint definitions
│ │ └── wine.routes.js
│ ├── .env # Local environment config (!!! DO NOT COMMIT !!!)
│ ├── package-lock.json
│ ├── package.json
│ └── server.js # Express server entry point
├── README.md # This file
└── REPORT.md # Detailed project report document
sshnot recognized: Install OpenSSH Client (Windows Optional Features) or use Git Bash / PuTTY. Check PATH.- SSH Key
No such file or directory: Verify the-ipath is exact. Use "Copy as path". Check filename. - SSH
Connection timed out: Verify Bastion Public IP. Check OCI Security Rule for Port 22 allows your current public IP. - SSH
Permission denied (publickey): Verify-ikey path. Check key permissions (Linux/macOS:chmod 400). Ensure correct key pair used. Verify bastion username (opc/ubuntu). - PuTTY Key: Use
puttygen.exeto convert key to.ppkformat if needed. - PuTTY Tunnel Not Working: Ensure tunnel rule (
L5433 ...) was Added in the Tunnels config. Keep PuTTY window open. - Node
ETIMEDOUT/ECONNREFUSED: SSH Tunnel not running or not listening on the correct local port (5433). Check OCI Security Rule for Port5432allows Bastion Private IP -> DB Private Subnet/NSG. - Node
ENOTFOUND:DB_HOSTin.envis wrong. Should belocalhostwhen using tunnel. - Node
password authentication failed for user "...": IncorrectDB_PASSWORDorDB_USERin.env. Reset password inpsqlif unsure. Remove quotes around password in.env. - Node
database ... does not exist: Database specified inDB_DATABASEdoesn't exist on OCI server. RunCREATE DATABASE ...;usingpsqlas admin. - Node SSL
Hostname/IP does not match...: SetDB_SSL_REJECT_UNAUTHORIZED=falsein.env. - Node SSL
certificate verify failed/unknown CA: VerifyDB_SSL_CA_CERT_FILENAMEin.envmatches the actual CA bundle file name (check if.pubis correct, usually.pem). Ensure file is inwine-quality-backend/certs/. Download the correct CA bundle from OCI. - YAML Errors on
npm start: Check JSDoc comments inroutes/wine.routes.jsfor incorrect indentation or use of tabs instead of spaces. Replace the maincomponents:block if needed.
Ian MwanikiEdgar NyoloDonnelly AmaitsaGloria AbinezaSafia Jamal