Skip to content
 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Parking Shark

Parking Shark is a full-stack, peer-to-peer parking marketplace built for the University of Virginia community. Renters can find an available driveway or garage, register a vehicle, book by the hour, pay, and review a completed stay. Hosts can publish listings, manage availability, confirm reservations, and export booking data.

Try the live demo · Read the case study

Parking Shark marketplace

We built this together as a four-person CS 4750 Database Systems project. A lot of the work happened side by side on shared computers. The application goes beyond CRUD: booking is transactional, overlap protection lives in both the database and application flow, and access to listings, vehicles, reservations, payments, and reviews is ownership-aware.

Highlights

  • Marketplace search by location, spot type, price, time window, and sort order
  • Host and renter dashboards with reservation lifecycle management
  • Atomic MySQL booking procedure with per-spot locking and overlap prevention
  • 13-table normalized relational model, stored procedure, trigger, constraints, role-scoped grants, reviews, payments, and CSV exports
  • Password hashing, session fixation defense, same-origin mutation checks, authentication rate limiting, security headers, and parameterized queries
  • Responsive server-rendered UI built with Express, EJS, Bootstrap, and custom CSS
  • Automated policy tests, dependency audit, and GitHub Actions CI

Architecture

Browser
  └── Express + EJS
       ├── authentication and MySQL-backed sessions
       ├── ownership and reservation-policy middleware
       ├── marketplace / host / renter routes
       └── mysql2 connection pool
            └── MySQL
                 ├── normalized marketplace data (13 tables)
                 ├── create_booking stored procedure
                 ├── prevent_double_booking trigger
                 └── CHECK constraints and least-privilege grants

The executable schema is in sql/schema.sql, which is the single source of truth for the database.

Parking Shark entity relationship diagram

Booking is conflict-safe at the database layer

Two people hitting "Reserve" on the same driveway for the same hour is the interesting concurrency problem in this project, and it is handled in SQL rather than in application code.

The subtlety is that the prevent_double_booking trigger alone is not enough. MySQL runs at REPEATABLE READ by default, and the trigger's overlap check is a plain non-locking read. Two concurrent transactions each get a snapshot taken before the other inserted, so both see zero conflicts and both commit.

create_booking closes that hole by taking an exclusive row lock on the spot before it checks anything:

SELECT hourly_rate INTO v_hourly_rate
FROM spots
WHERE spot_id = p_spot_id AND is_active = TRUE
FOR UPDATE;

That serializes booking attempts per listing. Because the locking read runs before any consistent read, the transaction's read view is created after the lock is granted, so the overlap check that follows sees the booking that just committed and raises SQLSTATE 45000. The reservation and its payment row are written in one transaction, and the extend path in routes/reservations.js takes the same locks in the same order so the two paths cannot deadlock against each other.

Measured on MySQL 9.0.1 with two connections issuing overlapping CALL create_booking at the same instant, 25 trials each:

Booking path Both succeeded Exactly one succeeded
With the FOR UPDATE row lock 0 25
Same procedure, lock removed 25 0

Run Locally

Requirements: Node.js 22 to 24 and MySQL 8 or newer.

git clone https://github.com/RohanSi4/parking-shark.git
cd parking-shark
npm ci
cp .env.example .env

Create a local database and seed it:

mysql -u root -p < sql/schema.sql
mysql -u root -p < sql/migration_auth.sql

Update .env with your local MySQL credentials and generate a session secret:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
npm run dev

Open http://localhost:3000. Seed accounts use the password password123:

  • fh@virginia.edu: renter with completed and upcoming reservations
  • ac@virginia.edu: host with listings and reviews

On macOS with Homebrew MySQL, bash setup.sh performs the same setup and starts the app. It never overwrites an existing .env or database.

Verify

npm test
npm run check

npm test runs the reservation-policy and request-origin regression suite. npm run check also verifies that production dependencies have no known audit findings. A fresh schema import should create 13 application tables, 15 seeded spots, 20 seeded reservations, the booking procedure, and overlap trigger.

Once running, GET /healthz verifies both the web process and its database connection without exposing credentials or internal errors.

Hosted portfolio demo

The repository now includes a Vercel-ready interactive demo. It is not a static mockup. A visitor can request a spot as a renter, switch to the host view to approve and complete the stay, then switch back to record payment and leave a review.

The demo uses signed, isolated cookie state and sample listings. That keeps the complete marketplace workflow available without exposing student accounts, collecting payment details, or depending on the unavailable course database. The original Express and MySQL application remains the source of truth for the database-backed product.

Run the hosted experience locally:

npm run demo

Deploy the repository root as an Other framework project on Vercel. The checked-in vercel.json sends application routes to api/index.js, bundles the demo views with that function, and lets Vercel serve the public assets as static files. No database environment variables are needed for the demo. DEMO_SESSION_SECRET can be set to a long random value to use a private signing key instead of the public-demo fallback.

npm run check
vercel build
vercel deploy --prebuilt

Database app deployment

The original course deployment used Google App Engine Standard and Cloud SQL. The legacy URL, https://parkingsharkuva.ue.r.appspot.com, is not currently a working public demo: as of July 2026, Google Frontend returns a service unavailable response before the Express app serves a page. The local app and a fresh database bootstrap are verified; the cloud deployment still needs an owner with project IAM access to inspect its serving version/logs and redeploy.

Copy deploy/app.yaml.example to the ignored deploy/app.yaml, set production environment variables, and deploy:

gcloud config set project YOUR_PROJECT_ID
gcloud app deploy deploy/app.yaml
curl https://YOUR_APP_URL/healthz

Production requires a strong SESSION_SECRET; startup fails fast if the value is missing or left as the example default. Set APP_ORIGIN when the public origin cannot be inferred from the incoming request. Real environment files and deployment credentials are intentionally excluded from Git.

Team

Built by Adithya Balasubramaniam, Rohan Singh, Angad Brar, and Visvajit Murali for CS 4750 Database Systems, January to April 2026.

The coursework phase was highly collaborative and frequently happened on shared machines, so commit authorship does not cleanly divide that work between the four of us. The schema, the Express application, and the original UI were a joint effort.

The hardening and portfolio pass in July 2026 was separate, and that work is mine alone. It is attributable through git log and git blame:

  • The concurrency fix described above. The FOR UPDATE row lock and the availability enforcement inside create_booking, plus the matching lock ordering on the reservation extend path.
  • middleware/security.js, the same-origin mutation check that rejects cross-site POSTs using Origin, Referer, and Fetch Metadata.
  • lib/reservation-policy.js, the reservation state machine that decides which role may confirm, complete, cancel, extend, pay, or review, extracted so it could be unit tested away from the database.
  • The whole test/ suite and the GitHub Actions workflow, including the CI step that imports the schema from scratch and asserts the table and seed counts.
  • The demo/ application and its Vercel entrypoint, which is what the live demo link serves.

About

Full-stack peer-to-peer parking marketplace with transactional bookings, host and renter workflows, and a live interactive demo.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages