This is the backend service for the AutoLocate Condo Parking system. It provides APIs for tenants, staff, and administrators to manage parking, guests, and RFID access.
- This markdown file has been generated by AI and has been proof-read & modified by human. It might contained some error that we didn't catch. Do not blindly trust.
- The API endpoints has been developed and test using postman. Please make sure that the cookie is enabled as it is used for authentication.
- The data record provided in the example below might not matched with the real data in your database. Please recheck with the provided
demo_insert.sqlfile or your own data. - You can directly create and populate the database with the provided
condo_parking.sqlfile anddemo_insert.sqlfile or use the exportedcondoparkingdb.sql.zipfile
- Server: Express (ES modules)
- Database: MySQL (via
mysql2/promise) - Authentication: JWT stored in an HttpOnly cookie (middleware in
middleware/auth.js) - Database Architecture: Three DB connection pools (in
db.js):adminPool,staffPool,tenantPool— each uses a DB user with appropriate privileges for security.
server.js— App bootstrap, middleware configuration, and router mounts.db.js— Database connection pools configuration.middleware/auth.js— JWT issuing/verifying and role-based access control middleware.routes/tenant.js— Tenant-related endpoints (login, car location, vehicle direction).routes/staff.js— Staff authentication and management endpoints (dashboard, guest management).routes/admin.js— Admin authentication and system management (staff/tenant creation, parking logs).routes/RFID.js— RFID gate authentication and logging endpoints.routes/auth.js— General authentication utilities (/me,/logout).scripts/seed_test_tenant.js— Demo/seed helper script.
- Node.js (v14 or higher)
- MySQL Database
- Clone the repository.
- Install dependencies:
npm install
- Set up the database:
- Create a database named
CondoParkingDB. - Run the SQL script
condo_parking.sqlto create tables and stored procedures. - (Optional) Run
demo_insert.sqlto seed the database with test data.
- Create a database named
- Configure environment variables:
- Create a
.envfile based on the example below.
- Create a
- Start the server:
npm start # or for development with nodemon npm run dev
Create a .env file in the root directory with the following variables:
PORT=3001
NODE_ENV=development
# Database Configuration
DB_HOST=localhost
DB_PORT=3306
DB_NAME=CondoParkingDB
# Database Users (Security Best Practice: Use different users with specific privileges)
ADMIN_DB_USER=adminpool
ADMIN_DB_PASS=admin_secure_password1
STAFF_DB_USER=staffpool
STAFF_DB_PASS=staff_secure_password1
TENANT_DB_USER=tenantpool
TENANT_DB_PASS=tenant_secure_password1
# JWT Configuration
JWT_SECRET=your_strong_jwt_secret
JWT_EXPIRES_IN=15m
JWT_COOKIE_NAME=token
JWT_COOKIE_MAX_AGE_MS=900000
JWT_SAMESITE=lax
# Set to 'true' in production with HTTPS
COOKIE_SECURE=false
# Optional: Domain for the cookie
# COOKIE_DOMAIN=.yourdomain.com
# Optional: Path for the cookie
COOKIE_PATH=/
# CORS Configuration
# Comma-separated list of allowed origins
FRONTEND_ORIGIN=http://localhost:3000,https://your-frontend-domain.com
# Optional: Send JWT in response body (useful for testing/dev)
# JWT_SEND_IN_BODY=truePORT=3001
DB_HOST=localhost
DB_PORT=3306
DB_NAME=CondoParkingDB
# Create a MySQL user with difference priviledge and include the username and password below Or use root for development convenience
TENANT_DB_USER="tenantpool"
TENANT_DB_PASS="tenant_secure_password1"
STAFF_DB_USER="staffpool"
STAFF_DB_PASS="staff_secure_password1"
ADMIN_DB_USER="adminpool"
ADMIN_DB_PASS="admin_secure_password1"
# JWT / Cookie configuration
JWT_SECRET="Super_Long_And_Complicated_JWT_Secret_key฿_&%$#@!~^*()_+{}|:<>?-=[];',./"
JWT_EXPIRES_IN=15m
JWT_COOKIE_NAME=auth_token
JWT_COOKIE_MAX_AGE_MS=900000
NODE_ENV="production"
# NODE_ENV="development"
# Set to 'true' to include JWT token in response body for frontend use (development/testing)
# Cookie/CORS behavior (production)
# FRONTEND_ORIGIN must match the actual frontend origin (protocol + host + port)
FRONTEND_ORIGIN=http://localhost:3000
JWT_SAMESITE=none # use 'none' for cross-site cookies
COOKIE_SECURE=true # must be true when JWT_SAMESITE=none (browsers require Secure)
COOKIE_DOMAIN=.notonoty.me # cookie available across subdomains.All API endpoints are prefixed with /api.
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/auth/me |
Get current logged-in user details | Yes |
POST |
/api/auth/logout |
Logout user (clears cookie) | No |
Example /api/auth/logout Body:
{
"username": "optional_username_for_logging"
}| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/tenant/auth |
Tenant Login | No |
GET |
/api/tenant/test-db-connection |
Test DB connection | No |
POST |
/api/tenant/carlocation |
Get car location | Yes (Tenant+) |
POST |
/api/tenant/vehicleDirection |
Get recent vehicle direction | Yes (Tenant+) |
Example /api/tenant/auth Body:
{
"username": "sophia_w",
"password": "tenant123"
}Example /api/tenant/carlocation Body:
{
"username": "sophia_w"
}Example /api/tenant/vehicleDirection Body:
{
"license_number": "AB-1234"
}| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/staff/auth |
Staff Login | No |
GET |
/api/staff/tenants |
List all tenants | Yes (Staff+) |
POST |
/api/staff/parking_log_search |
Search parking logs | Yes (Staff+) |
POST |
/api/staff/dashboard |
Get dashboard statistics | Yes (Staff+) |
POST |
/api/staff/guest_management |
Register a guest visit | Yes (Staff+) |
Example /api/staff/auth Body:
{
"username": "janesmith",
"password": "staff123"
}Example /api/staff/guest_management Body:
{
"license_number": "GV-8888",
"brand": "Honda",
"model": "Civic",
"color": "Black",
"firstname": "Alice",
"lastname": "Wonder",
"gender": "F",
"note": "Visiting room 501",
"room_id": 501,
"guest_RFID_TID": "TID_GUEST_006",
"visit_EPC": "EPC_GUEST_006",
"staff_id": 2
}| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/admin/auth |
Admin Login | No |
GET |
/api/admin/staff-info |
Get all staff information | Yes (Admin+) |
GET |
/api/admin/get/staff/:id |
Get single staff details | Yes (Admin+) |
POST |
/api/admin/staff |
Create new staff | Yes (Admin+) |
PATCH |
/api/admin/staff/:id |
Update staff details | Yes (Admin+) |
GET |
/api/admin/tenants |
List tenants (paginated) | Yes (Admin+) |
GET |
/api/admin/tenants/:id |
Get single tenant details | Yes (Admin+) |
POST |
/api/admin/tenants |
Create new tenant | Yes (Admin+) |
PATCH |
/api/admin/tenants/:id |
Update tenant details | Yes (Admin+) |
GET |
/api/admin/tenants/:id/visits |
List visits for a tenant | Yes (Admin+) |
GET |
/api/admin/guest-visits |
List all guest visits | Yes (Admin+) |
POST |
/api/admin/guest-visits |
Create guest visit | Yes (Admin+) |
GET |
/api/admin/parking_log |
Get parking logs | Yes |
POST |
/api/admin/parking_log |
Get parking logs (via body) | Yes |
Example /api/admin/auth Body:
{
"username": "johndoe",
"password": "admin123"
}Example /api/admin/staff (Create) Body:
{
"username": "new_staff_member",
"password": "password123",
"first_name": "Alice",
"last_name": "Smith",
"position": "Security",
"access_level": "Staff",
"is_Active": true
}Example /api/admin/tenants (Create) Body:
{
"username": "new_tenant_user",
"password": "password123",
"first_name": "Bob",
"last_name": "Jones",
"phone": "0812345678",
"email": "[email protected]",
"gender": "M",
"is_primary_contact": true,
"room_id": 501,
"is_Active": true
}Example /api/admin/parking_log Body:
{
"date": "2025-11-20",
"license_number": "AB-1234"
}| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/rfid/authenticate |
Authenticate RFID at gate | No |
GET |
/api/rfid/gate-logs |
List gate logs | Yes (Staff+) |
POST |
/api/rfid/gate-logs |
Create manual gate log | Yes (Staff+) |
GET |
/api/rfid/gate-logs/:id |
Get single gate log | Yes (Staff+) |
PATCH |
/api/rfid/gate-logs/:id |
Update gate log | Yes (Staff+) |
DELETE |
/api/rfid/gate-logs/:id |
Delete gate log | Yes (Staff+) |
GET |
/api/rfid/tags |
List RFID tags | Yes (Staff+) |
POST |
/api/rfid/tags |
Create RFID tag | Yes (Staff+) |
PATCH |
/api/rfid/tags/:tid |
Update RFID tag | Yes (Staff+) |
DELETE |
/api/rfid/tags/:tid |
Delete RFID tag | Yes (Staff+) |
Example /api/rfid/authenticate Body:
{
"rfid_tid": "TID_TENANT_501",
"rfid_epc": "EPC_TENANT_501",
"gate_name": "Main Gate",
"direction": "Arrival"
}Example /api/rfid/tags (Create) Body:
{
"rfid_tid": "TID_NEW_TAG",
"current_EPC": "EPC_NEW_TAG",
"tag_type": "Guest",
"tag_status": "Available",
"license_number": "XYZ-1234"
}- Live API Endpoint: The backend is deployed and accessible at
https://testapi.notonoty.me/. You can use this for testing if you don't want to run the server locally. (likely not available outside the demo period) - Local Development: By default, the server runs on
http://localhost:3001. - Security:
- Passwords are hashed using
bcryptbefore storage. - JWT tokens are used for authentication and are stored in HttpOnly cookies.
- Passwords are hashed using