Clinic management system. Supports the management of staff, offices, appointments, patients and medical records.
The project implements Clean Architecture, CQRS pattern, MediatR, minimal api with api versioning, repository pattern, EF, custom JWT authorization, fluent validation.
- .NET 8
- ASP.NET Core 8
- Entity Framework Core
- SQL Server 2022
- FluentValidation
- IdentityModel
- MediatR
- Carter
- Asp.Versioning
- Swashbuckle
- Bogus
- Docker
-
app - container for all application layers
-
database - MSSQL database container
-
cloudbeaver - graphical access to SQLServer
The first time the containers are launched, random data generation will be performed to check the functionality (Bogus package).
-
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 |
---|---|---|---|---|
database | 1433 | SA | Dev_password@1 | - |
cloudbeaver | 9000 | - | - | http://localhost:9000 |
app | 8080 | - | - | http://localhost:8080/swagger/index.html |
-
Swagger UI
http://localhost:5000/swagger/index.html
-
https://github.com/gitEugeneL/RightPlace/blob/main/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/login
(allows you to login, issues accessToken and sets refreshToken in cookies)
name type data type required string password required string
http code content-type response 200
application/json
{"type: "Bearer", "accessToken": "eyJhbGciOi..........."}
400
application/json
array
name example refreshToken refreshToken=Wna@3da...; Expires=...; Secure; HttpOnly; Domain=...;`
POST
/api/v1/auth/refresh
(allows to refresh access and refresh tokens)
name example refreshToken refreshToken=Wna@3da...;
http code content-type response 200
application/json
{"type: "Bearer", "accessToken": "eyJhbGciOi..........."}
400
application/json
array
401
application/json
string
POST
/api/v1/auth/logout
(allows to logout and deactivates refresh token)
- Valid access JWT Bearer token in the header
http code content-type response 204
application/json
and remove HttpOnly Cookie
NoCOntent
400
application/json
string
401
application/json
string
Functionality that allows to manage and interact with managers
POST
/api/v1/manager
(allows to register new manager 🔒️[admin policy])
name type data type "email" required string "password" required string
http code content-type response 201
application/json
{"userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "position": "string"}
400
application/json
array
401
application/json
string
403
application/json
string
409
application/json
string
PUT
/api/v1/manager
(allows to update manager account 🔒️[manager policy])
name type data type "firstName" not required string "lastName" not required string "phone" not required string "position" not required string
http code content-type response 200
application/json
{"userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "position": "string"}
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
Functionality that allows to manage and interact with doctors
POST
/api/v1/doctor
(allows to create new doctor 🔒️[manager policy])
name type data type "email" required string "password" required string
http code content-type response 201
application/json
{"userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "status": "string", "description": "string", "education": "string", "appointmentSettingsId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "specializationIds": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ] }
400
application/json
array
401
application/json
string
403
application/json
string
409
application/json
string
PUT
/api/v1/doctor
(allows to update doctor account 🔒️[doctor policy])
name type data type "firstName" not required string "lastName" not required string "phone" not required string "status" not required string "description" not required string "education" not required string
http code content-type response 200
application/json
{"userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "status": "string", "description": "string", "education": "string", "appointmentSettingsId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "specializationIds": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ] }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
GET
/api/v1/doctor
(allows to get all doctors)
name type data type PageNumber not required int32 PageSize not required int32
http code content-type response 200
application/json
{"items": [ { "userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "status": "string", "description": "string", "education": "string", "appointmentSettingsId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "specializationIds": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ] } ], "pageNumber": 0, "totalPages": 0, "totalItemsCount": 0 }
GET
/api/v1/doctor/{ userId:uuid }
(allows to get one doctor)
http code content-type response 200
application/json
{"userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "status": "string", "description": "string", "education": "string", "appointmentSettingsId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "specializationIds": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ] }
404
application/json
string
Functionality that allows to manage and interact with patients
POST
/api/v1/patient
(allows to register new patient)
name type data type "email" required string "password" required string
http code content-type response 201
application/json
{ "userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "pesel": "string", "dateOfBirth": "string", "insurance": "string", "addressId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }
400
application/json
array
409
application/json
string
PUT
/api/v1/patient
(allows to update your patient account 🔒[patient policy])
name type data type "firstName" not required string "lastName" not required string "phone" not required string "pesel" not required string "dateOfBirth" not required string "insurance" not required string "firstName" not required string
http code content-type response 200
application/json
{ "userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "pesel": "string", "dateOfBirth": "string", "insurance": "string", "addressId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
DELETE
/api/v1/patient
(allows to delete your patient account 🔒[patient policy])
http code content-type response 204
application/json
NoContent
401
application/json
string
403
application/json
string
404
application/json
string
GET
/api/v1/patient
(allows to get all patients 🔒[doctor-or-manager policy])
name type data type PageNumber not required int32 PageSize not required int32
http code content-type response 204
application/json
{"items": [ { "userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "pesel": "string", "dateOfBirth": "string", "insurance": "string", "addressId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" } ], "pageNumber": 0, "totalPages": 0, "totalItemsCount": 0 }
401
application/json
string
403
application/json
string
GET
/api/v1/patient{ userId:uuid: }
(allows to get one patient 🔒[doctor-or-manager policy])
http code content-type response 200
application/json
{"userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "pesel": "string", "dateOfBirth": "string", "insurance": "string", "addressId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }
401
application/json
string
403
application/json
string
404
application/json
string
Functionality allows to manage the patients' addresses (entity is created automatically when a patient is registered)
PUT
/api/v1/address
(allows to update patient address 🔒[patient policy])
name type data type "province" not required string "postalCode" not required string "city" not required string "street" not required string "house" not required string "apartment" not required string
http code content-type response 200
application/json
{"province": "string", "postalCode": "string", "city": "string", "street": "string", "hose": "string", "apartment": "string" }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
GET
/api/v1/address/{ addressId:uuid }
(allows to get patient's address 🔒[doctor-or-manager policy])
http code content-type response 200
application/json
{"province": "string", "postalCode": "string", "city": "string", "street": "string", "hose": "string", "apartment": "string"}
401
application/json
string
403
application/json
string
404
application/json
string
Functionality that allows to manage and interact with appointments
GET
/api/v1/appointment/find-time/{ userDoctorId:uuid }/{ date:string }
(allows find doctor's free time 🔒[patient policy])
http code content-type response 200
application/json
{ "userDoctorId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "freeHours": [ { "start": "08:00", "end": "09:00" } ] }
401
application/json
string
403
application/json
string
404
application/json
string
422
application/json
string
POST
/api/v1/appointment
(allows to create new appointment 🔒[patient policy])
name type data type "userDoctorId" required uuid "date" required string "startTime" required string
http code content-type response 201
application/json
{"appointmentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userPatientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userDoctorId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "date": "string", "startTime": "string", "endTime": "string", "isCompleted": true, "isCanceled": true }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
POST
/api/v1/appointment/{ date:string }
(allows to get your personal an appointment list 🔒[token required])
http code content-type response 200
application/json
[ { "appointmentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userPatientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userDoctorId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "date": "string", "startTime": "string", "endTime": "string", "isCompleted": true, "isCanceled": true } ]
401
application/json
string
403
application/json
string
404
application/json
string
422
application/json
string
PUT
/api/v1/appointment/finalise/{ appointmentId:uuid }
(allows to finalise an appointment 🔒[doctor policy])
http code content-type response 200
application/json
{"appointmentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userPatientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userDoctorId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "date": "string", "startTime": "string", "endTime": "string", "isCompleted": true, "isCanceled": true }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
422
application/json
string
PUT
/api/v1/appointment/cancel/{ appointmentId:uuid }
(allows to cancel an appointment 🔒[doctor policy])
http code content-type response 200
application/json
{"appointmentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userPatientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userDoctorId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "date": "string", "startTime": "string", "endTime": "string", "isCompleted": true, "isCanceled": true }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
422
application/json
string
Functionality for configuring doctors' appointments settings (entity is created automatically when a doctor is created)
PUT
/api/v1/appointment-settings
(allows to config a doctor 🔒[doctor policy])
name type data type "startTime" required string "endTime" required string "interval" required string "workdays" required array
http code content-type response 200
application/json
{ "startTime": "10:00", "endTime": "17:00", "interval": "30M", "workdays": [ 1, 2, 3, 4, 5 ] }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
422
application/json
string
GET
/api/v1/appointment-settings/{ settingsId:uuid }
(allows to get a doctor's configuration 🔒[token required])
http code content-type response 200
application/json
{"startTime": "08:00, "endTime": "15:00", "interval": "1H", "workdays": [ 1, 2, 4, 5 ] }
401
application/json
string
403
application/json
string
404
application/json
string
Functionality that allows to manage and interact with specializations
POST
/api/v1/specialization
(allows to create new specialization 🔒[manager policy])
name type data type "value" required string "description" not required string
http code content-type response 201
application/json
{ "specializationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "value": "string", "description": "string", "userDoctorIds": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ] }
400
application/json
array
401
application/json
string
403
application/json
string
409
application/json
string
PUT
/api/v1/specialization
(allows to update specialization 🔒[manager policy])
name type data type "specializationId" required uuid "description" not required string
http code content-type response 201
application/json
{ "specializationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "value": "string", "description": "string", "userDoctorIds": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ] }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
DELETE
/api/v1/specialization/{ specializationId:uuid }
(allows to delete specialization 🔒[manager policy])
http code content-type response 204
application/json
NoContent
401
application/json
string
403
application/json
string
404
application/json
string
GET
/api/v1/specialization
(allows to get all specialization)
http code content-type response 200
application/json
[{ "specializationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "value": "string", "description": "string", "userDoctorIds": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ] } ]
PUT
/api/v1/specialization/include-doctor
(allows to include a doctor 🔒[manager policy])
name type data type "specializationId" required uuid "userDoctorId" required uuid
http code content-type response 200
application/json
{ "specializationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "value": "string", "description": "string", "userDoctorIds": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ] } ]
401
application/json
string
403
application/json
string
404
application/json
string
409
application/json
string
PUT
/api/v1/specialization/exclude-doctor
(allows to exclude a doctor 🔒[manager policy])
name type data type "specializationId" required uuid "userDoctorId" required uuid
http code content-type response 200
application/json
{ "specializationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "value": "string", "description": "string", "userDoctorIds": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ] } ]
401
application/json
string
403
application/json
string
404
application/json
string
409
application/json
string
Functionality that allows to manage and interact with medical records
POST
/api/v1/medical-record
(allows to create medical records 🔒[doctor policy])
name type data type "appointmentId" required uuid "userPatientId" required uuid "title" required string "doctorNote" not required string
http code content-type response 201
application/json
{ "medicalRecordId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userPatientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userDoctorId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "appointmentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "title": "string", "doctorNote": "string", "created": "2024-04-20T19:46:52.893Z" }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
409
application/json
string
PUT
/api/v1/medical-record
(allows to update medical records 🔒[doctor policy])
name type data type "medicalRecordId" required uuid "title" not required string "doctorNote" not required string
http code content-type response 200
application/json
{ "medicalRecordId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userPatientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userDoctorId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "appointmentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "title": "string", "doctorNote": "string", "created": "2024-04-20T19:50:45.998Z" }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
GET
/api/v1/medical-record/{ medicalRecordId:uuid }
(allows to get one medical record 🔒[doctor-or-patient policy])
http code content-type response 200
application/json
{ "medicalRecordId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userPatientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userDoctorId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "appointmentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "title": "string", "doctorNote": "string", "created": "2024-04-20T19:53:30.118Z" }
401
application/json
string
403
application/json
string
404
application/json
string
GET
/api/v1/medical-record/for-patient
(allows to get your records 🔒[patient policy])
name type data type SortByDate not required boolean SortOrderAsc not required boolean PageNumber not required int32 PageSize not required int32
http code content-type response 200
application/json
{ "items": [ { "medicalRecordId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userPatientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userDoctorId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "appointmentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "title": "string", "doctorNote": "string", "created": "2024-04-20T19:55:13.407Z" } ], "pageNumber": 0, "totalPages": 0, "totalItemsCount": 0 }
401
application/json
string
403
application/json
string
404
application/json
string
GET
/api/v1/medical-record/for-doctor
(allows to get your records 🔒[doctor policy])
name type data type UserPatientId not required uuid SortByDate not required boolean SortOrderAsc not required boolean PageNumber not required int32 PageSize not required int32
http code content-type response 200
application/json
{ "items": [ { "medicalRecordId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userPatientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "userDoctorId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "appointmentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "title": "string", "doctorNote": "string", "created": "2024-04-20T19:55:13.407Z" } ], "pageNumber": 0, "totalPages": 0, "totalItemsCount": 0 }
401
application/json
string
403
application/json
string
404
application/json
string
Functionality that allows to manage and interact with offices
POST
/api/v1/office
(allows to create new office 🔒[manager policy])
name type data type "name" required string "number" required int
http code content-type response 201
application/json
{ "officeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "number": 201, "isAvailable": true }
400
application/json
array
401
application/json
string
403
application/json
string
409
application/json
string
PUT
/api/v1/office
(allows to update offices 🔒[manager policy])
name type data type "officeId" required uuid "name" required string
http code content-type response 200
application/json
{ "officeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "number": 201, "isAvailable": true }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
PATCH
/api/v1/office
(allows to lock or unlock an office 🔒[doctor-or-manager policy])
name type data type "officeId" required uuid
http code content-type response 200
application/json
{ "officeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "number": 201, "isAvailable": true }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
GET
/api/v1/office
(allows to get all offices 🔒[doctor-or-manager policy])
http code content-type response 200
application/json
[ { "officeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "number": 10, "isAvailable": true } ]
400
application/json
array
401
application/json
string
403
application/json
string