Skip to content

Commit fb4d613

Browse files
feat: API users and auth service
routes for : /api/v1/users service to match password PasswordUtils for authentication
2 parents 852c1e8 + 7b2a603 commit fb4d613

23 files changed

Lines changed: 2411 additions & 10 deletions

.env.example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Database Configuration
2+
DATABASE_URL="mysql://username:password@localhost:3306/database_name"
3+
4+
# Example for local MySQL:
5+
# DATABASE_URL="mysql://root:password@localhost:3306/odp_frontend"
6+
7+
# Example for PlanetScale:
8+
# DATABASE_URL="mysql://username:password@aws.connect.psdb.cloud/database_name?sslaccept=strict"

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,16 @@ pnpm-debug.log*
1616
# environment variables
1717
.env
1818
.env.production
19+
.env.local
1920

2021
# macOS-specific files
2122
.DS_Store
2223

2324
# jetbrains setting folder
2425
.idea/
2526

26-
specs/
27+
specs/
28+
29+
# Prisma
30+
.env
31+
prisma/migrations/

API.md

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# API Documentation
2+
3+
## Base URL
4+
All API endpoints are prefixed with `/api/v1`
5+
6+
## Users API
7+
8+
### GET /api/v1/users
9+
Get all users or filter users by criteria.
10+
11+
**Query Parameters:**
12+
- `id`: Get specific user by ID
13+
- `status`: Filter by user status (`signup`, `active`, `disabled`)
14+
- `role_id`: Filter by role ID
15+
16+
**Response:**
17+
```json
18+
{
19+
"success": true,
20+
"data": [
21+
{
22+
"id": 1,
23+
"email": "user@example.com",
24+
"name": "John Doe",
25+
"phone": "+1234567890",
26+
"picture": "https://example.com/avatar.jpg",
27+
"role_id": 1,
28+
"status": "active",
29+
"created_at": "2024-01-01T00:00:00.000Z",
30+
"role": {
31+
"id": 1,
32+
"name": "Admin",
33+
"description": "Administrator role"
34+
}
35+
}
36+
],
37+
"count": 1
38+
}
39+
```
40+
41+
### POST /api/v1/users
42+
Create a new user.
43+
44+
**Request Body:**
45+
```json
46+
{
47+
"email": "user@example.com",
48+
"name": "John Doe",
49+
"password": "password123",
50+
"password_confirmation": "password123",
51+
"phone": "+1234567890",
52+
"picture": "https://example.com/avatar.jpg",
53+
"role_id": 1,
54+
"status": "signup"
55+
}
56+
```
57+
58+
**Required Fields:**
59+
- `email`
60+
- `name`
61+
- `password`
62+
- `role_id`
63+
64+
**Response:**
65+
```json
66+
{
67+
"success": true,
68+
"data": {
69+
"id": 1,
70+
"email": "user@example.com",
71+
"name": "John Doe",
72+
"phone": "+1234567890",
73+
"picture": "https://example.com/avatar.jpg",
74+
"role_id": 1,
75+
"status": "signup",
76+
"created_at": "2024-01-01T00:00:00.000Z",
77+
"role": {
78+
"id": 1,
79+
"name": "Admin",
80+
"description": "Administrator role"
81+
}
82+
},
83+
"message": "User created successfully"
84+
}
85+
```
86+
87+
### PUT /api/v1/users
88+
Update an existing user.
89+
90+
**Request Body:**
91+
```json
92+
{
93+
"id": 1,
94+
"email": "updated@example.com",
95+
"name": "Updated Name",
96+
"phone": "+0987654321",
97+
"status": "active"
98+
}
99+
```
100+
101+
**Required Fields:**
102+
- `id`
103+
104+
**Response:**
105+
```json
106+
{
107+
"success": true,
108+
"data": {
109+
"id": 1,
110+
"email": "updated@example.com",
111+
"name": "Updated Name",
112+
"phone": "+0987654321",
113+
"picture": "https://example.com/avatar.jpg",
114+
"role_id": 1,
115+
"status": "active",
116+
"created_at": "2024-01-01T00:00:00.000Z",
117+
"role": {
118+
"id": 1,
119+
"name": "Admin",
120+
"description": "Administrator role"
121+
}
122+
},
123+
"message": "User updated successfully"
124+
}
125+
```
126+
127+
## Error Responses
128+
129+
All endpoints return errors in the following format:
130+
131+
```json
132+
{
133+
"success": false,
134+
"error": "Error message description"
135+
}
136+
```
137+
138+
**Common HTTP Status Codes:**
139+
- `200`: Success
140+
- `201`: Created
141+
- `400`: Bad Request
142+
- `404`: Not Found
143+
- `409`: Conflict (e.g., email already exists)
144+
- `500`: Internal Server Error
145+
146+
## Authentication
147+
148+
Currently, no authentication is implemented. In production, you should add:
149+
- JWT authentication
150+
- Role-based authorization
151+
- Password hashing (bcrypt)
152+
- Rate limiting
153+
- Input sanitization

PRISMA_SETUP.md

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# Prisma DB Integration Setup
2+
3+
This project now includes a complete Backend-for-Frontend (BFF) layer with Prisma ORM integration following clean architecture and SOLID principles.
4+
5+
## 🏗️ Architecture Overview
6+
7+
```
8+
src/bff/
9+
├── db/
10+
│ ├── prisma/
11+
│ │ └── schema.prisma # Database schema with Users & Roles
12+
│ ├── client.ts # Prisma client singleton
13+
│ └── index.ts # DB bootstrap functions
14+
├── types/
15+
│ └── index.ts # TypeScript interfaces
16+
├── repositories/
17+
│ ├── user.repository.ts # User data access layer
18+
│ ├── role.repository.ts # Role data access layer
19+
│ └── index.ts # Repository exports
20+
├── services/
21+
│ ├── user.service.ts # User business logic layer
22+
│ └── index.ts # Service exports
23+
└── index.ts # Main BFF exports
24+
```
25+
26+
## 🚀 Quick Start
27+
28+
### 1. Database Setup
29+
30+
1. Copy the environment template:
31+
```bash
32+
cp .env.example .env
33+
```
34+
35+
2. Update your `.env` file with your MySQL database URL:
36+
```
37+
DATABASE_URL="mysql://username:password@localhost:3306/database_name"
38+
```
39+
40+
### 2. Generate Prisma Client
41+
42+
```bash
43+
npm run db:generate
44+
```
45+
46+
### 3. Push Schema to Database
47+
48+
```bash
49+
npm run db:push
50+
```
51+
52+
### 4. Run the Development Server
53+
54+
```bash
55+
npm run dev
56+
```
57+
58+
## 📊 Database Schema
59+
60+
### Users Table
61+
- `id` (number, primary key)
62+
- `email` (string, unique)
63+
- `name` (string)
64+
- `password` (string)
65+
- `phone` (string, optional)
66+
- `picture` (string, optional)
67+
- `role_id` (number, foreign key)
68+
- `status` (enum: signup, active, disabled)
69+
- `created_at` (datetime)
70+
71+
### Roles Table
72+
- `id` (number, primary key)
73+
- `name` (string)
74+
- `description` (string)
75+
76+
### Relationships
77+
- User `belongsTo` Role (via `role_id`)
78+
- Role `hasMany` Users
79+
80+
## 🔌 API Endpoints
81+
82+
### GET /api/v1/users
83+
- Get all users or filter by criteria
84+
- Query params: `id`, `status`, `role_id`
85+
86+
### POST /api/v1/users
87+
- Create new user
88+
- Required: `email`, `name`, `password`, `role_id`
89+
90+
### PUT /api/v1/users
91+
- Update existing user
92+
- Required: `id` in request body
93+
94+
See [API.md](./API.md) for detailed endpoint documentation.
95+
96+
## 🛠️ Available Scripts
97+
98+
```bash
99+
# Generate Prisma client
100+
npm run db:generate
101+
102+
# Push schema changes to database
103+
npm run db:push
104+
105+
# Open Prisma Studio (database GUI)
106+
npm run db:studio
107+
108+
# Build project
109+
npm run build
110+
111+
# Start development server
112+
npm run dev
113+
```
114+
115+
## 🏛️ Architecture Principles
116+
117+
### Clean Architecture
118+
- **Repository Layer**: Handles data access and database queries
119+
- **Service Layer**: Contains business logic and validation
120+
- **API Layer**: HTTP request/response handling
121+
122+
### SOLID Principles Applied
123+
- **Single Responsibility**: Each class has one reason to change
124+
- **Open/Closed**: Easily extendable without modification
125+
- **Liskov Substitution**: Repository interfaces can be swapped
126+
- **Interface Segregation**: Focused, specific interfaces
127+
- **Dependency Inversion**: Services depend on abstractions
128+
129+
### Key Features
130+
- ✅ Strongly typed Prisma client
131+
- ✅ Testable repository pattern
132+
- ✅ Business logic separation
133+
- ✅ Role relationships populated
134+
- ✅ Input validation
135+
- ✅ Error handling
136+
- ✅ Type safety throughout
137+
138+
## 🔧 Customization
139+
140+
### Adding New Entities
141+
1. Update `schema.prisma` with new model
142+
2. Run `npm run db:generate` and `npm run db:push`
143+
3. Create repository in `src/bff/repositories/`
144+
4. Create service in `src/bff/services/`
145+
5. Add API routes in `src/pages/api/v1/`
146+
147+
### Authentication (TODO)
148+
In production, consider adding:
149+
- JWT authentication
150+
- Password hashing with bcrypt
151+
- Role-based authorization
152+
- Rate limiting
153+
- Input sanitization
154+
155+
## 🚨 Important Notes
156+
157+
- **Development Only**: Current password handling is not secure
158+
- **Database Required**: You need a MySQL database to run the API endpoints
159+
- **SSR Mode**: Project is configured for server-side rendering
160+
- **Node.js Adapter**: Using @astrojs/node for deployment

astro.config.mjs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
// @ts-check
22
import { defineConfig } from "astro/config";
33
import tailwindcss from "@tailwindcss/vite";
4-
54
import react from "@astrojs/react";
5+
import node from "@astrojs/node";
66

77
// https://astro.build/config
88
export default defineConfig({
99
integrations: [react()],
10+
output: "server", // Changed from "static" to enable SSR and API routes
11+
adapter: node({
12+
mode: "standalone",
13+
}),
1014
vite: {
1115
plugins: [tailwindcss()],
1216
ssr: {
@@ -16,9 +20,8 @@ export default defineConfig({
1620
include: ["@material-tailwind/react"],
1721
},
1822
},
19-
//TEMP config for static demo with Github pages
20-
site: "https://inria.github.io",
21-
base: "/inocs-sum-odp-frontend",
22-
output: "static",
23+
//TEMP config for static demo with Github pages (commented out for SSR)
24+
// site: "https://inria.github.io",
25+
// base: "/inocs-sum-odp-frontend",
2326
build: { assets: "assets" }, // replaces the default "_astro"
2427
});

0 commit comments

Comments
 (0)