This is a rest api service for course management at the university.
The project implements minimal api with api versioning, repository pattern, custom JWT authorization, fluent validation, integration and unit tests.
- xUnit
- .NET 8
- ASP.NET Core 8
- Entity Framework Core 8
- PostgreSQL
- FluentValidation
- IdentityModel
- Asp.Versioning
- Swashbuckle
- Docker
Allows you to run all integration and unit tests.
> dotnet test # donet SKD is required
-
api.app - container for all application layers
-
api.database - postgresql database container
-
Build and start Docker images based on the configuration defined in the docker-compose.yml
> make up # docker-compose up --build
-
Stop and remove containers
> make down # docker-compose down
container | port | login | password | GUI |
---|---|---|---|---|
api.database | 5432 | user | password | - |
api.app | 8000 | - | - | http://localhost:8000/swagger/index.html |
-
Swagger UI
http://localhost:8000/swagger/index.html
-
https://github.com/gitEugeneL/Course-management-system/blob/dev/swagger.json
Authentication is implemented using a JWT access token and refresh token.
AccessToken is used to authorize users, the refresh token is used to update a pair of tokens.
RefreshToken is recorded in the database and allows each user to have 5 active devices at the same time.
POST
/api/v1/auth/register
(allows you to register)
name type data type required string password required string firstName not required string lastName not required string universityNumber not required string
http code content-type response 201
application/json
{"userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "universityNumber": "string"}
400
application/json
array
409
application/json
string
POST
/api/v1/auth/register
(allows you to login, issues accessToken and refreshToken)
name type data type required string password required string
http code content-type response 200
application/json
{"accessTokenType": "string", "accessToken": "string", "refreshToken": "string", "refreshTokenExpires": "2024-04-19T18:14:59.908Z"}
400
application/json
array
404
application/json
string
POST
/api/v1/auth/refresh
(allows to refresh access and refresh tokens)
name type data type "refreshToken" required string
http code content-type response 200
application/json
{"accessTokenType": "string", "accessToken": "string", "refreshToken": "string", "refreshTokenExpires": "2024-04-19T18:14:59.908Z"}
401
application/json
string
POST
/api/v1/auth/refresh
(allows to logout and deactivates refresh token)
name type data type "refreshToken" required string
http code content-type response 204
application/json
NoContent
401
application/json
string
Functionality that allows to manage and interact with courses
POST
/api/v1/courses
(allows to create new course 🔒️[professor auth policy])
name type data type "name" required string "description" required string "maxParticipants" required int
http code content-type response 201
application/json
{"courseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6","ownerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "description": "string", "maxParticipants": 0, "countParticipants": 0, "finalized": true, "createdAt": "2024-04-19T18:37:43.448Z"}
400
application/json
array
401
application/json
string
403
application/json
string
409
application/json
string
PUT
/api/v1/courses
(allows to update your courses 🔒️[professor auth policy])
name type data type "courseId" required uuid "description" required string "maxParticipants" required int "finalize" required boolean
http code content-type response 200
application/json
{"courseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "ownerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "description": "string", "maxParticipants": 0, "countParticipants": 0, "finalized": true, "createdAt": "2024-04-19T18:50:26.257Z"}
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
PUT
/api/v1/courses/{ courseName:string }
(allows to delete your courses 🔒️[professor auth policy])
http code content-type response 204
application/json
NoContent
401
application/json
string
403
application/json
string
404
application/json
string
PATCH
/api/v1/courses/join/{ courseName:string }
(allows to join the course 🔒️[student auth policy])
http code content-type response 200
application/json
stging
401
application/json
string
403
application/json
string
404
application/json
string
409
application/json
string
PATCH
/api/v1/courses/leave/{ courseName:string }
(allows to leave the course 🔒️[student auth policy])
http code content-type response 200
application/json
stging
401
application/json
string
403
application/json
string
404
application/json
string
409
application/json
string
GET
/api/v1/courses
(allows you to get all courses 🔒️[base auth policy])
name type data type SortByCreated not required boolean SortByAvailableCourses not required boolean SortByMyCourses not required boolean PageNumber not required int32 PageSize not required int32
http code content-type response 200
application/json
{ "items": [ { "courseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "ownerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "description": "string", "maxParticipants": 0, "countParticipants": 0, "finalized": true, "createdAt": "2024-04-19T19:04:00.291Z" } ], "pageNumber": 0, "totalPages": 0, "totalItemsCount": 0 }
401
application/json
string
403
application/json
string
GET
/api/v1/courses/{ courseName:string }
(allows you to get one course by name 🔒️[base auth policy])
http code content-type response 200
application/json
{"courseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "ownerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "description": "string", "maxParticipants": 0, "countParticipants": 0, "finalized": true, "createdAt": "2024-04-19T19:07:27.865Z"}
401
application/json
string
403
application/json
string
404
application/json
string
Functionality that allows to manage course participants
PATCH
/api/v1/participants
(allows you to grade the student 🔒️[professor auth policy])
name type data type "userId" required uuid "courseId" required uuid "grade" required int "professorNote" required string
http code content-type response 200
application/json
{"course": { "courseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "ownerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "description": "string", "maxParticipants": 0, "countParticipants": 0, "finalized": true, "createdAt": "2024-04-19T19:40:56.771Z" }, "user": { "userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "universityNumber": "string" }, "grade": 0, "professorNote": "string"}
401
application/json
string
403
application/json
string
404
application/json
string
GET
/api/v1/participants/{ courseName:string }
(allows you to grade the student 🔒️[professor auth policy])
name type data type PageNumber not required int32 PageSize not required int32
http code content-type response 200
application/json
{"items": [ { "course": { "courseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "ownerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "description": "string", "maxParticipants": 0, "countParticipants": 0, "finalized": true, "createdAt": "2024-04-19T19:50:54.089Z" }, "user": { "userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "universityNumber": "string" } ,"grade": 0, "professorNote": "string" } ], "pageNumber": 0, "totalPages": 0, "totalItemsCount": 0 }
401
application/json
string
403
application/json
string
404
application/json
string
GET
/api/v1/participants
(allows you to get all your participants and courses 🔒️[student auth policy])
http code content-type response 200
application/json
{{"course": { "courseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "ownerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "description": "string", "maxParticipants": 0, "countParticipants": 0, "finalized": true, "createdAt": "2024-04-19T19:43:59.773Z" }, "user": { "userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "universityNumber": "string" }, "grade": 0, "professorNote": "string"}}
401
application/json
string
403
application/json
string