Files
MetaCourseApi/BACKEND_API_DOCS.md
T
2026-05-05 10:39:43 +02:00

491 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MetaCourse API — Frontend Integration Guide
> Target stack: Angular + Capacitor
> Base URL (local): `http://localhost:8080`
> Base URL (production): `http://romaric-thibault.fr`
---
## Deployment
### Requirements
- Docker + Docker Compose installed on the server
### Start the stack
```bash
docker compose up -d --build
```
The API will be available on port **8080**. SQL Server runs on port **1433** (internal). Migrations run automatically on startup.
### Swagger UI
```
http://<host>:8080/swagger
```
---
## Authentication
There is **no JWT** currently. Login returns user info directly. Store `UserId` in local storage / Capacitor Preferences to identify the current user across requests.
---
## Data Models (TypeScript interfaces)
```typescript
// Enums
type CourseStatus = 'Draft' | 'Published';
type ResourceType = 'Url' | 'Video' | 'Text' | 'File';
interface User {
id: string; // Guid
name: string;
email: string;
createdAt: string; // ISO date
}
interface LoginResponse {
userId: string;
name: string;
email: string;
}
interface Course {
id: string;
title: string;
description: string;
status: CourseStatus;
creatorId: string;
creatorName: string;
topicCount: number;
createdAt: string;
updatedAt: string;
}
interface CourseDetails extends Course {
topics: Topic[];
}
interface Topic {
id: string;
title: string;
description?: string;
position: number;
courseId: string;
resources: Resource[];
}
interface Resource {
id: string;
type: ResourceType;
title: string;
content: string; // URL, video URL, text body, or file path
createdAt: string;
}
interface Enrollment {
userId: string;
courseId: string;
courseTitle: string;
enrolledAt: string;
completedAt?: string;
}
interface CourseProgress {
courseId: string;
userId: string;
totalTopics: number;
completedTopics: number;
totalResources: number;
completedResources: number;
progressPercentage: number; // 0.0 - 100.0
}
```
---
## API Endpoints
### Users
#### Register
```
POST /api/users/register
```
**Body:**
```json
{
"name": "Alice",
"email": "alice@example.com",
"password": "Password1"
}
```
**Validation:** name 2100 chars, valid email, password ≥8 chars + 1 uppercase + 1 digit
**Response:** `201``User`
**Errors:** `400` validation | `409` email already taken
---
#### Login
```
POST /api/users/login
```
**Body:**
```json
{
"email": "alice@example.com",
"password": "Password1"
}
```
**Response:** `200``LoginResponse`
**Errors:** `401` wrong credentials
---
#### Get User Profile
```
GET /api/users/{id}
```
**Response:** `200``User` | `404`
---
### Courses
#### List Published Courses
```
GET /api/courses
```
Optional query param: `?search=angular`
**Response:** `200``Course[]` (only Published courses, newest first)
---
#### Get Course with Topics & Resources
```
GET /api/courses/{id}
```
**Response:** `200``CourseDetails` | `404`
---
#### Create Course
```
POST /api/courses
```
**Body:**
```json
{
"title": "Introduction to Angular",
"description": "Learn Angular from scratch",
"creatorId": "<userId>"
}
```
**Response:** `201``Course` (status = `Draft`)
---
#### Update Course
```
PUT /api/courses/{id}
```
**Body:**
```json
{
"id": "<courseId>",
"title": "Updated Title",
"description": "Updated description"
}
```
**Response:** `200``Course` | `404`
---
#### Publish Course
```
PATCH /api/courses/{id}/publish
```
**Response:** `200``Course` | `422` if no topics yet | `404`
---
#### Delete Course
```
DELETE /api/courses/{id}
```
**Response:** `204` | `409` if course has enrollments | `404`
---
#### Courses Created by a User
```
GET /api/users/{userId}/courses
```
**Response:** `200``Course[]`
---
### Topics
#### Get Topic
```
GET /api/topics/{id}
```
**Response:** `200``Topic` (includes resources ordered by position) | `404`
---
#### Create Topic
```
POST /api/topics
```
**Body:**
```json
{
"courseId": "<courseId>",
"title": "Components",
"description": "Optional description",
"position": 1
}
```
**Response:** `201``Topic`
---
#### Update Topic
```
PUT /api/topics/{id}
```
**Body:**
```json
{
"id": "<topicId>",
"title": "Updated Title",
"description": "Updated",
"position": 2
}
```
**Response:** `200``Topic` | `404`
---
#### Delete Topic
```
DELETE /api/topics/{id}
```
**Response:** `204` | `404`
---
#### Link Resource to Topic
```
POST /api/topics/{topicId}/resources/{resourceId}
```
**Body:**
```json
{ "position": 1 }
```
**Response:** `204`
---
#### Unlink Resource from Topic
```
DELETE /api/topics/{topicId}/resources/{resourceId}
```
**Response:** `204`
---
### Resources
#### List All Resources
```
GET /api/resources
```
**Response:** `200``Resource[]` (ordered by creation date desc)
---
#### Get Resource
```
GET /api/resources/{id}
```
**Response:** `200``Resource` | `404`
---
#### Create Resource
```
POST /api/resources
```
**Body:**
```json
{
"type": "Url",
"title": "Angular Docs",
"content": "https://angular.io"
}
```
**Types & content:**
| Type | content field |
|------|--------------|
| `Url` | Full URL (https required) |
| `Video` | Video URL (https required) |
| `Text` | Markdown or plain text body |
| `File` | File path or download URL |
**Response:** `201``Resource`
---
#### Update Resource
```
PUT /api/resources/{id}
```
**Body:**
```json
{
"id": "<resourceId>",
"type": "Video",
"title": "Updated",
"content": "https://youtube.com/..."
}
```
**Response:** `200``Resource` | `404`
---
#### Delete Resource
```
DELETE /api/resources/{id}
```
**Response:** `204` | `404`
---
### Enrollments
#### Enroll in a Course
```
POST /api/courses/{courseId}/enroll
```
**Body:**
```json
{
"userId": "<userId>",
"courseId": "<courseId>"
}
```
**Response:** `201``Enrollment`
**Errors:** `409` already enrolled | `422` course not Published | `404`
---
#### User's Enrollments
```
GET /api/users/{userId}/enrollments
```
**Response:** `200``Enrollment[]`
---
### Progress
#### Mark Topic Progress
```
POST /api/topics/{topicId}/progress
```
**Body:**
```json
{
"userId": "<userId>",
"topicId": "<topicId>",
"completed": true
}
```
**Response:** `204` (upsert — safe to call multiple times)
---
#### Mark Resource Progress
```
POST /api/resources/{resourceId}/progress
```
**Body:**
```json
{
"userId": "<userId>",
"resourceId": "<resourceId>",
"completed": true
}
```
**Response:** `204` (upsert)
---
#### Get Course Progress
```
GET /api/courses/{courseId}/progress?userId={userId}
```
**Response:** `200``CourseProgress`
```json
{
"courseId": "...",
"userId": "...",
"totalTopics": 5,
"completedTopics": 3,
"totalResources": 10,
"completedResources": 7,
"progressPercentage": 66.67
}
```
---
## Error Response Format
All validation and business errors follow this shape:
```json
{
"statusCode": 400,
"errors": {
"email": ["'Email' is not a valid email address."],
"password": ["Password must be at least 8 characters."]
}
}
```
---
## CORS
All origins, methods, and headers are allowed (`AllowAll` policy). No special headers needed from Angular/Capacitor.
---
## Typical User Flow (Angular/Capacitor)
```
1. POST /api/users/register → store userId in Capacitor Preferences
2. POST /api/users/login → verify credentials
3. GET /api/courses → show published course catalog
4. GET /api/courses/{id} → show course detail with topics
5. POST /api/courses/{id}/enroll → enroll user
6. GET /api/users/{id}/enrollments → show My Courses
7. POST /api/topics/{id}/progress → mark topic done
8. POST /api/resources/{id}/progress → mark resource done
9. GET /api/courses/{id}/progress?userId=... → show progress bar
```
---
## Notes for Angular Service Layer
- All IDs are **UUIDs (string)** — no integer IDs.
- Dates are **ISO 8601 UTC strings** — use `new Date(dateString)` or a pipe.
- `progressPercentage` is a `number` (float 0100), round for display.
- `status` and `type` come back as **strings**, not numbers.
- No auth headers needed currently — all endpoints are `AllowAnonymous`.