Skip to content

devcavin/gatelog

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Gatelog - Digital Visitor Management System

A production-grade visitor management system built to replace paper logbooks with a fast, searchable, and accountable web application.


What is Gatelog?

Gatelog is a digital visitor management system designed for any single-site premises, a corporate office, a clinic, a school, or a residential estate. It replaces paper-based visitor logbooks with a structured, role-aware, and cloud-deployable web application.

The project is built to demonstrate end-to-end product engineering: system design, backend API development, cloud deployment, CI/CD, and security-conscious development practices.


Live Demo

Coming soon...


Stack

Layer Technology
Backend Kotlin + Spring Boot 3
Database PostgreSQL (Supabase)
Auth Spring Security + JWT
ORM Spring Data JPA / Hibernate
Migrations Flyway
Docs SpringDoc OpenAPI / Swagger UI
CI/CD GitHub Actions + GHCR
Deployment Render (compute) + Supabase (db)

Architecture

┌─────────────────────────────────────────┐
│              React Frontend             │  ← Phase 2
│         (TypeScript + Vite)             │
└────────────────────┬────────────────────┘
                     │ HTTPS / REST
┌────────────────────▼────────────────────┐
│           Spring Boot Backend           │
│                                         │
│  ┌─────────────┐   ┌─────────────────┐  │
│  │ Controllers │   │ Security Filter │  │
│  └──────┬──────┘   └────────┬────────┘  │
│         │                   │ JWT        │
│  ┌──────▼───────────────────▼────────┐  │
│  │           Service Layer           │  │
│  └──────────────────┬────────────────┘  │
│                     │                   │
│  ┌──────────────────▼────────────────┐  │
│  │       Spring Data JPA / Flyway    │  │
│  └──────────────────┬────────────────┘  │
└─────────────────────┼───────────────────┘
                      │
┌─────────────────────▼───────────────────┐
│         PostgreSQL (Supabase)           │
└─────────────────────────────────────────┘

Data Model

roles ──────────────────────────► users
visit_statuses ─────────────────► visitors
sites ──────────────────────────► zones
                                  users
                                  visitors
zones ──────────────────────────► visitors (nullable)
users ──────────────────────────► visitors (created_by)
                                  refresh_tokens

All primary keys are UUID. Enums are replaced with lookup tables (roles, visit_statuses) for clean migrations and audit flexibility.


Project Structure

gatelog/
├── backend/
│   ├── src/main/kotlin/io/github/devcavin/backend/
│   │   ├── common/exception/      # domain exception hierarchy
│   │   ├── config/                # security, CORS config
│   │   ├── domain/
│   │   │   ├── model/             # JPA entities
│   │   │   └── repository/        # Spring Data repositories
│   │   ├── security/              # JWT provider, filter, UserDetails
│   │   ├── service/               # business logic
│   │   └── web/
│   │       ├── controller/        # REST controllers
│   │       ├── dto/               # request/response DTOs
│   │       └── error/             # global exception handler
│   ├── src/main/resources/
│   │   ├── db/migration/          # Flyway migrations v1–v7
│   │   ├── application.yaml       # shared config (env var placeholders)
│   │   └── application-local.yaml # local dev overrides (gitignored)
│   ├── Dockerfile                 # multi-stage build
│   └── compose.yaml               # local Postgres via Docker
├── .github/workflows/
│   └── ci.yml                     # test → build image → push to GHCR
└── README.md

API Endpoints

Auth — /api/auth

Method Endpoint Auth Description
POST /login Public Login, returns JWT pair
POST /refresh Public Rotate refresh token
POST /logout Public Invalidate refresh token

Users — /api/users

Method Endpoint Auth Description
POST / SUPER_ADMIN, MANAGER Create a user

Managers can only create Staff accounts scoped to their own site. Super Admin can create any role at any site.

Visitors — /api/visitors (in progress)

Method Endpoint Auth Description
POST / All roles Register a new visitor
GET /{id} All roles Get visitor by ID
PATCH /{id}/checkout All roles Check out a visitor
GET / All roles Search visitors (paginated)
GET /returning All roles Returning visitor phone lookup

Role-Based Access Control

Role Capabilities
SUPER_ADMIN Full access, users, config, all analytics, all visitor records
MANAGER Reports, analytics, visitor records, create Staff users at own site
STAFF Register visitors, check in/out, view active visitors, search history

Role enforcement happens at two layers: @PreAuthorize on controllers (HTTP level) and explicit business rules in the service layer (domain level).


Running Locally

Prerequisites: Docker, JDK 21, Git

# 1. clone
git clone https://github.com/devcavin/gatelog.git
cd gatelog/backend

# 2. start postgres
docker compose up -d

# 3. run the app (local profile auto-activates)
SPRING_PROFILES_ACTIVE=local \
DB_URL=jdbc:postgresql://localhost:5432/gatelog \
DB_USERNAME=postgres \
DB_PASSWORD=secret \
JWT_SECRET=local-dev-secret-key-must-be-at-least-256-bits-long-for-hs256 \
CORS_ALLOWED_ORIGINS=http://localhost:5173 \
./gradlew bootRun

# 4. open swagger
open http://localhost:8080/swagger-ui/index.html

Flyway runs all migrations automatically on startup. The database is seeded with roles, visit statuses, a default site, and a Super Admin account.


Environment Variables

Variable Description Required
DB_URL JDBC connection URL Yes
DB_USERNAME Database username Yes
DB_PASSWORD Database password Yes
JWT_SECRET HS256 signing key (min 256 bits) Yes
JWT_ACCESS_EXPIRY_MS Access token expiry in ms (default 900000) No
JWT_REFRESH_EXPIRY_DAYS Refresh token expiry in days (default 7) No
CORS_ALLOWED_ORIGINS Allowed frontend origins Yes
SPRING_PROFILES_ACTIVE Active Spring profile No

CI/CD

Every push to main that touches backend/**:

  1. Test - runs the full test suite with Testcontainers (real Postgres)
  2. Build image - multi-stage Docker build, pushed to GHCR with SHA tag and latest
ghcr.io/devcavin/gatelog-backend:latest
ghcr.io/devcavin/gatelog-backend:<short-sha>

Roadmap

Phase 1 - Core System (in progress)

  • Database schema and Flyway migrations
  • JWT authentication with refresh token rotation
  • Role-based access control (Super Admin, Manager, Staff)
  • User registration endpoint with role enforcement
  • CI pipeline with GitHub Actions
  • Visitor registration and check-in/check-out
  • Real-time dashboard endpoints
  • Visitor search with dynamic filters
  • CSV export
  • React frontend

Phase 2 - Intelligence Layer (planned)

  • SMS OTP verification (Africa's Talking / Twilio)
  • Analytics dashboard
  • Zone routing and host notifications
  • PDF export
  • Scheduled report delivery
  • Kubernetes deployment with Helm
  • Observability with Prometheus and Grafana

Architecture Decisions

Why lookup tables over enums? PostgreSQL enums cannot have values removed without recreating the type, making migrations fragile. Lookup tables (roles, visit_statuses) keep migrations clean and make audit queries straightforward.

Why no offline mode? Cloud hosting is a deliberate architectural choice. The system trades offline capability for real-time data availability, automated backups, and searchability, none of which paper can provide.

Why layered monolith over Spring Modulith? For a single-developer MVP, a clean layered monolith ships faster and is more familiar to most engineering teams reviewing the code. Spring Modulith is the right next step if the domain grows and team size increases, that migration path is documented and the package structure supports it without a full rewrite.



Built by @devcavin

About

Gatelog: Digital Visitor Management System

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors