Skip to content

Latest commit

 

History

History
447 lines (313 loc) · 9.45 KB

API_README.md

File metadata and controls

447 lines (313 loc) · 9.45 KB

RabbitHR - Backend API Documentation

Overview

RabbitHR now features a professional-grade backend API built with modern TypeScript technologies, replacing the localStorage-based data persistence with a real SQLite database.

Tech Stack

Backend

  • Hono - Ultra-fast, lightweight web framework
  • Drizzle ORM - TypeScript-first ORM with excellent type safety
  • SQLite (better-sqlite3) - Zero-config file-based database
  • JWT (jsonwebtoken) - Secure authentication
  • bcryptjs - Password hashing
  • Zod - Runtime type validation

Frontend Integration

  • Axios - HTTP client with interceptors
  • TanStack Query - Data fetching and caching
  • TypeScript - End-to-end type safety

Architecture

/api
├── /db
│   ├── schema.ts        # Drizzle schema definitions
│   ├── client.ts        # Database connection
│   └── seed.ts          # Initial data seeding
├── /middleware
│   ├── auth.ts          # JWT authentication
│   └── error.ts         # Error handling
├── /routes
│   ├── auth.ts          # Authentication endpoints
│   ├── feedback.ts      # Feedback CRUD
│   ├── absences.ts      # Absences management
│   └── employees.ts     # Employee directory
└── server.ts            # Main Hono app

/src/services
└── api.ts               # Axios client & API methods

Setup Instructions

1. Install Dependencies

npm install

2. Environment Variables

Create .env file in project root (use .env.example as template):

API_PORT=3001
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
DATABASE_PATH=./data/database.db

Create .env.local for frontend:

VITE_API_URL=http://localhost:3001

3. Initialize Database

# Push schema to database and seed initial data
npm run db:setup

This creates:

  • 3 users (admin, manager, employee) - all with password password123
  • Sample feedback entries
  • Sample absence requests

4. Start Development Servers

# Starts both API server and frontend concurrently
npm run dev

The backend API runs on http://localhost:3001
The frontend runs on http://localhost:8081 (or 8080 if available)

API Endpoints

Authentication

POST /api/auth/login

Login with email and password, returns JWT token

Request:

{
  "email": "admin@company.com",
  "password": "password123"
}

Response:

{
  "user": {
    "id": "uuid",
    "email": "admin@company.com",
    "name": "Admin User",
    "role": "admin",
    "department": "Management",
    "position": "System Administrator",
    "avatar": "...",
    "managerId": null
  },
  "token": "jwt-token-here"
}

GET /api/auth/me

Get current authenticated user (requires JWT)

Headers:

Authorization: Bearer <jwt-token>

Feedback

GET /api/feedback

Get all feedback (sent or received by current user)

POST /api/feedback

Create new feedback

Request:

{
  "toUserId": "uuid",
  "content": "Great work!",
  "polishedContent": "Excellent work on the project...",
  "type": "positive",
  "status": "sent"
}

PATCH /api/feedback/:id

Update feedback (only if you're the sender)

DELETE /api/feedback/:id

Delete feedback (only if you're the sender)

Absences

GET /api/absences

Get absences (employees see own, managers/admins see all)

POST /api/absences

Create absence request

Request:

{
  "type": "vacation",
  "startDate": "2024-12-20T00:00:00.000Z",
  "endDate": "2024-12-27T00:00:00.000Z",
  "reason": "Holiday vacation"
}

PATCH /api/absences/:id

Update pending absence (only your own)

POST /api/absences/:id/approve

Approve/reject absence (managers/admins only)

Request:

{
  "status": "approved" // or "rejected"
}

DELETE /api/absences/:id

Delete pending absence (only your own)

Employees

GET /api/employees

Get all employees (managers/admins only)

GET /api/employees/:id

Get single employee (managers/admins only)

GET /api/employees/manager/:managerId

Get direct reports of a manager

Database Schema

Users Table

  • id (UUID primary key)
  • email (unique)
  • password (bcrypt hashed)
  • name
  • role (admin | manager | employee)
  • department
  • position
  • avatar
  • managerId (foreign key to users)
  • createdAt, updatedAt

Feedback Table

  • id (UUID primary key)
  • fromUserId (foreign key to users)
  • toUserId (foreign key to users)
  • content
  • polishedContent (optional)
  • type (positive | constructive | development)
  • status (draft | sent)
  • createdAt, updatedAt

Absences Table

  • id (UUID primary key)
  • userId (foreign key to users)
  • type (vacation | sick | personal | other)
  • startDate, endDate (ISO strings)
  • reason
  • status (pending | approved | rejected)
  • approvedBy (foreign key to users, nullable)
  • createdAt, updatedAt

Authentication Flow

  1. User logs in via /api/auth/login
  2. Server validates credentials, returns JWT token
  3. Frontend stores token in localStorage
  4. All subsequent API requests include token in Authorization: Bearer <token> header
  5. Backend middleware validates token and extracts user info
  6. Routes enforce role-based access control

Authorization Rules

Feedback

  • Users can create feedback for any other user
  • Users can read feedback they sent or received
  • Users can only edit/delete feedback they created

Absences

  • Employees can create, view, edit, and delete their own pending absences
  • Managers can view all team absences and approve/reject them
  • Admins can view all absences and approve/reject them

Employees

  • Only managers and admins can access employee directory
  • Managers see their direct reports
  • Admins see all employees

Development Scripts

npm run dev              # Start both API and frontend
npm run dev:api          # Start API server only
npm run dev:frontend     # Start Vite frontend only

npm run db:generate      # Generate migration files
npm run db:push          # Push schema to database
npm run db:seed          # Seed database with initial data
npm run db:setup         # Push schema + seed (full setup)
npm run db:studio        # Open Drizzle Studio GUI

npm run build            # Build for production
npm run preview          # Preview production build

Testing the API

Default Users

All users have password: password123

  1. Admin User

    • Email: admin@company.com
    • Role: admin
    • Can access all features
  2. Manager User

    • Email: manager@company.com
    • Role: manager
    • Can approve absences, view team members
  3. Employee User

    • Email: employee@company.com
    • Role: employee
    • Can submit feedback and absences

Using the API

You can test endpoints using:

  • The frontend UI at http://localhost:8081
  • cURL or Postman for direct API calls
  • Drizzle Studio for database inspection: npm run db:studio

Example cURL:

# Login
curl -X POST http://localhost:3001/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@company.com","password":"password123"}'

# Get feedback (with token from login)
curl http://localhost:3001/api/feedback \
  -H "Authorization: Bearer <your-token>"

Security Features

  • Password Hashing: bcrypt with salt rounds
  • JWT Authentication: Secure token-based auth with 7-day expiration
  • Role-Based Access Control: Enforced at API level
  • Input Validation: Zod schemas for all inputs
  • SQL Injection Prevention: Drizzle ORM parameterized queries
  • CORS Protection: Whitelisted origins only

Data Persistence

All data is stored in ./data/database.db SQLite file. This file persists across server restarts, demonstrating real backend functionality to examiners.

To reset the database:

rm -rf data/
npm run db:setup

Frontend Integration

The frontend uses TanStack Query for data fetching with automatic caching, refetching, and optimistic updates:

// Example: Fetching feedback
const { data: feedbacks, isLoading } = useQuery({
  queryKey: ["feedback"],
  queryFn: feedbackAPI.getAll,
});

// Example: Creating feedback
const mutation = useMutation({
  mutationFn: feedbackAPI.create,
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ["feedback"] });
  },
});

Production Deployment

For production:

  1. Change JWT_SECRET to a strong random value
  2. Use environment-specific .env files
  3. Consider using PostgreSQL instead of SQLite for scalability
  4. Add rate limiting and additional security headers
  5. Enable HTTPS
  6. Set up proper error monitoring (Sentry, etc.)
  7. Configure database backups

Troubleshooting

Port Already in Use

If port 3001 or 8080 is busy, change in .env:

API_PORT=3002

Database Locked

If you see "database is locked" errors:

# Stop all processes
pkill -f tsx
pkill -f vite
# Restart
npm run dev

CORS Errors

Ensure frontend URL is in CORS whitelist in api/server.ts

Authentication Errors

Check that JWT token is being sent in headers and hasn't expired (7 days)

Contributing

When adding new features:

  1. Define database schema in api/db/schema.ts
  2. Create migrations with npm run db:generate
  3. Add API routes in api/routes/
  4. Add validation schemas (Zod)
  5. Create frontend API methods in src/services/api.ts
  6. Update components to use TanStack Query
  7. Test thoroughly with all user roles

Built with professional-grade patterns for demonstration to examiners 🚀