Skip to content

Latest commit

Β 

History

55 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🏍️ BikeLog

BikeLog is a multi-user motorcycle logbook. It replaces a single-page, localStorage-based HTML app with a proper Spring Boot + JPA backend, secured by Google OAuth 2.0 and JWT, so multiple people can each track their own bikes: rides, fuel fill-ups, oil changes, tyre pressure, service history, and monthly/overall statistics.

Status: Actively developed, pre-1.0. Core ride/fuel tracking and the dashboard work end-to-end; several modules described in the API contract (oil changes, tyre checks, service history, oil/tyre status widgets) are still stubs. See Project Status & Roadmap below β€” this is intentional, so the project has a clear on-ramp for contributors.


Table of Contents


How it works

  1. The user logs in with Google OAuth 2.0 from the frontend.
  2. On successful login, the backend creates the user (if new) and issues a JWT, then redirects back to the frontend with the token in the URL.
  3. The frontend stores the token and sends it as Authorization: Bearer <token> on every subsequent API call.
  4. A custom JwtFilter validates the token on each request and puts the user's ID into the Spring Security context, so controllers can read the current user via @AuthenticationPrincipal.
  5. Each user can own multiple bikes. Every ride, fuel entry, and maintenance record belongs to a bike, which belongs to a user β€” all queries are scoped so users can only ever see their own data.
  6. The bike's currentOdo is recalculated automatically after every new ride or fuel entry, as the max of initialOdo, the latest ride odometer, and the latest fuel-entry odometer.
  7. Fuel mileage (km/litre) is computed retroactively: when a new fuel entry is logged, the previous entry gets its distanceKm and mileageKmPerLitre filled in using the odometer difference between the two fill-ups. The most recent fuel entry always has null mileage until the next fill-up closes the loop.

Features

Implemented

  • Google OAuth 2.0 login β†’ JWT issuance β†’ stateless JWT auth on every request
  • Multi-bike support per user, with an "active bike" preference
  • Ride logging with auto-computed distance since the last odometer reading
  • Fuel fill-up logging with auto-computed litres, cumulative litres, distance-per-tank, and mileage (km/l)
  • Odometer integrity checks (new entries can't be logged behind the bike's current odometer)
  • Monthly dashboard: km driven, litres used, spend, riding days, best/current mileage
  • Overall (all-time) stats with a month-by-month breakdown for charting
  • Month picker data source (/{bikeId}/months)

Designed but not yet implemented (see roadmap)

  • Oil change tracking + oil-change-due reminder
  • Tyre pressure check tracking + latest front/rear summary
  • Workshop/service history
  • Delete-bike (cascade delete of all its records)

Tech stack

Layer Technology
Language / runtime Java 21
Framework Spring Boot 4.1 (Web, Security, OAuth2 Client, Data JPA)
Auth Google OAuth 2.0 (login) + JWT (API access), via jjwt
Database H2 (in-memory, current) β†’ MySQL (planned, see roadmap)
Mapping MapStruct (entity ↔ DTO)
Build Gradle
Frontend Static HTML/CSS/JS in frontend/ (no framework/build step)

Project structure

bikelog/
β”œβ”€β”€ src/main/java/com/mybikelog/api/
β”‚   β”œβ”€β”€ config/          # SecurityConfig, CORS, OAuth2 success handler
β”‚   β”œβ”€β”€ controller/      # REST controllers (one per resource)
β”‚   β”œβ”€β”€ service/         # Business logic
β”‚   β”œβ”€β”€ repository/      # Spring Data JPA repositories
β”‚   β”œβ”€β”€ entity/          # JPA entities
β”‚   β”œβ”€β”€ dto/             # Request/response DTOs
β”‚   β”œβ”€β”€ mapper/          # MapStruct mapper interfaces
β”‚   β”œβ”€β”€ filter/          # JwtFilter
β”‚   └── util/            # JWTUtil, NumberUtil, AppConstants
β”œβ”€β”€ src/main/resources/
β”‚   β”œβ”€β”€ application.yaml
β”‚   └── application-oauth.yml
β”œβ”€β”€ frontend/            # Static HTML/CSS/JS client (separate app, same repo)
β”œβ”€β”€ docs/
β”‚   └── my-bike-log-swagger.yml      # Full API contract (source of truth for endpoints/DTOs)
β”œβ”€β”€ build.gradle
└── README.md

If you're browsing the repo and don't see frontend/ or docs/my-bike-log-swagger.yml yet, they're being reorganized into this layout β€” see issues for tracking.

Architecture

  • Controller β†’ Service β†’ Repository, standard layered Spring Boot design. Controllers stay thin: they just extract the authenticated user ID (@AuthenticationPrincipal), delegate to a service, and wrap the result in a ResponseEntity.
  • CommonService centralizes logic shared across services β€” fetching a bike scoped to its owner, and recalculating currentOdo after any ride/fuel mutation.
  • MapStruct (MapperClass) handles all entity ↔ DTO conversion, including a generic Page<E> β†’ PageDTO<D> mapper used by every paginated list endpoint.
  • Security: SecurityConfig wires up oauth2Login() for the browser-based Google login flow and a custom JwtFilter (ahead of UsernamePasswordAuthenticationFilter) for stateless API auth on every other request. CustomAuthenticationSuccessHandler is where a successful Google login turns into an app JWT and a redirect back to the frontend.
  • Ownership scoping: nearly every repository query is findBy...AndUserId(...) (or via the bike, AndBikeId(...)) so cross-user data access isn't possible even if a bike/ride/entry ID is guessed.

API overview

The full contract β€” every endpoint, request/response schema, and validation rule β€” lives in docs/my-bike-log-swagger.yml. You can paste it into the Swagger Editor to browse it interactively. Highlights:

Resource Base path Notes
Users /users/me Get/patch current user profile & active bike
Bikes /bikes CRUD for a user's bikes
Rides /rides/{bikeId} Log/list/delete odometer readings
Petrol /petrol-entries/{bikeId} Log/list/delete fuel fill-ups; mileage computed automatically
Oil Changes /oil-changes/{bikeId} Planned
Tyre Checks /tyre-checks/{bikeId} Planned
Services /services/{bikeId} Planned
Dashboard & Stats /{bikeId}/months, /{bikeId}/dashboard, /{bikeId}/overall-stats, /{bikeId}/oil-status, /{bikeId}/tyre-status Monthly and all-time stats; the last two are stubbed

All endpoints except OAuth2 login require Authorization: Bearer <jwt>.

Getting started

Prerequisites

  • JDK 21
  • A Google OAuth 2.0 client ID/secret (Web application type, with an authorized redirect URI of http://localhost:8080/login/oauth2/code/google for local dev)
  • (Frontend) Any static file server β€” e.g. VS Code's Live Server extension, since the frontend currently expects to run at http://127.0.0.1:5500

Backend

git clone https://github.com/arshadpatel/my-bike-log.git
cd my-bike-log

export JWT_SECRET="a-long-random-string-at-least-32-bytes"
export GOOGLE_CLIENT_ID="your-google-client-id"
export GOOGLE_CLIENT_SECRET="your-google-client-secret"

./gradlew bootRun

The API will be available at http://localhost:8080. H2 is in-memory, so data resets on every restart β€” the H2 console is available at /h2-console for inspecting it while developing.

Frontend

cd frontend
# open index.html with a static server, e.g.:
npx live-server --port=5500

Log in via the "Sign in with Google" flow; the backend will redirect back to http://127.0.0.1:5500/index.html?token=... with the JWT.

Configuration

Variable Required Description
JWT_SECRET Yes HMAC signing key for JWTs. Use a long random string.
GOOGLE_CLIENT_ID Yes From Google Cloud Console OAuth credentials.
GOOGLE_CLIENT_SECRET Yes From Google Cloud Console OAuth credentials.

jwt.expiration-time (in application.yaml) controls token lifetime in milliseconds; defaults to 1 hour.


🚧 Project status & roadmap

This project is being open-sourced specifically to grow through contributions, so here's an honest snapshot of what's solid vs. what's a good first issue.

βœ… Working end-to-end

  • Google OAuth login β†’ JWT issuance
  • Bike CRUD (create, list, get, update)
  • Ride logging, listing (with month filter + pagination), deletion
  • Petrol entry logging, listing, deletion, with auto-computed litres/mileage/cumulative litres
  • Monthly dashboard stats
  • Overall stats with monthly breakdown

🧩 Stubbed / not implemented (great first issues)

  • Delete bike (DELETE /bikes/{bikeId}) β€” controller method exists but returns null; needs a service method that cascades deletes across rides/petrol/oil/tyre/service records.
  • Oil status (GET /{bikeId}/oil-status) β€” controller returns null; needs the OilChange entity/repo/service plus the due/overdue calculation described in the OpenAPI spec.
  • Tyre status (GET /{bikeId}/tyre-status) β€” same situation, needs the TyreCheck entity/repo/service.
  • Oil Changes module β€” entity, repository, service, controller (/oil-changes/{bikeId}) don't exist yet; only speced in the OpenAPI contract.
  • Tyre Checks module β€” same, for /tyre-checks/{bikeId}.
  • Service (workshop) history module β€” same, for /services/{bikeId}.

πŸ—ΊοΈ Planned / architectural

  • Migrate from H2 to MySQL for real persistence (currently in-memory only, wiped on every restart).
  • Global exception handling β€” replace scattered RuntimeExceptions with a @ControllerAdvice that returns the ErrorResponse/ValidationErrorResponse shapes already defined in the OpenAPI contract (with correct 400/404/409 status codes).
  • Bean Validation on request DTOs to match the constraints already documented in the OpenAPI spec (e.g. odo must be positive, name length limits).
  • Externalize CORS/redirect URLs β€” http://127.0.0.1:5500 is currently hardcoded in SecurityConfig and CustomAuthenticationSuccessHandler, which blocks any non-local deployment.
  • Automated tests β€” there currently aren't any; unit tests for services and integration tests for controllers would be very welcome.
  • Reorganize repo into backend/ (or keep at root) + frontend/ + docs/my-bike-log-swagger.yml as described in Project structure.

If you find issues, please open an issue β€” see CONTRIBUTING.md.

Contributing

Contributions are very welcome β€” see CONTRIBUTING.md for how to get set up, coding conventions, and how issues/PRs are handled.

License

MIT β€” free to use, modify, and distribute, with attribution.

About

Spring Boot API for tracking bike rides, fuel mileage, and maintenance - multi-user, Google OAuth + JWT secured

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages