Final project on the subject of "Cloud-oriented web applications".
This is a rest api service for the real estate portal. The project implements Clean Architecture, CQRS, MediatR, Repository pattern, custom JWT authorization, file storage in minIO object storage.
- .NET 7
- ASP.NET Core 7
- Entity Framework Core 7
- MediatR
- Mapster
- IdentityModel
- PostgreSQL
- MinIO
- Bogus
- Asp.Versioning
- Swashbuckle
- Docker
-
app - container for all application layers
-
database - postgresql database container
-
pgadmin - graphical access to databases
-
minio - store static files from users
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 |
---|---|---|---|---|
minIO storage | 9001 | dev_user | dev_password | http://localhost:9001/login |
database | 5432 | dev_user | dev_pwd | - |
pgadmin | 8080 | dev@dev.com | dev_pwd | http://localhost:9000/login |
app | 5000 | - | - | http://localhost:5000/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", "token": "eyJhbGciOi..........."}
400
application/json
array
403
application/json
string
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", "token": "eyJhbGciOi..........."}
403
application/json
string
name example refreshToken refreshToken=Wna@3da...; Expires=...; Secure; HttpOnly; Domain=...;`
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 200
application/json
and remove HttpOnly Cookie
No body returned for response
401
application/json
string
403
application/json
string
Functionality that allows to manage and interact with users
POST
/api/v1/users
(allows you to register)
name type data type required string password required string
http code content-type response 201
application/json
{"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "dateOfBirth": "2024-04-16"}
400
application/json
array
409
application/json
string
GET
/api/v1/users
(allows you to return the list of users)
name type data type PageNumber not required int32 PageSize not required int32
http code content-type response 200
application/json
{"items": [ {"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "dateOfBirth": "2024-04-16"} ], "pageNumber": 0, "totalPages": 0, "totalItemsCount": 0 }
401
application/json
string
403
application/json
string
GET
/api/v1/users/{ userId:uuid }
(allows you to return user profile)
http code content-type response 200
application/json
{"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "dateOfBirth": "2024-04-16"}
401
application/json
string
403
application/json
string
404
application/json
string
PUT
/api/v1/users
(allows to update personal profile)
name type data type firstName not required string lastName not required string phone not required string dateOfBirth not required string
http code content-type response 200
application/json
{"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "dateOfBirth": "2024-04-16"}
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
DELETE
/api/v1/users
(allows to delete personal profile)
http code content-type response 204
application/json
No Content
401
application/json
string
403
application/json
string
404
application/json
string
Functionality that allows to manage and interact with adverts
POST
/api/v1/advertisements
(allows you to create an advert)
name type data type categoryId required uuid typeId required uuid title required string description required string price required int
http code content-type response 201
application/json
{ "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "title": "string", "description": "string", "price": 0, "images": [ "string" ], "categoryId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "typeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "addressId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "informationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "created": "2024-04-16T16:35:50.556Z", "updated": "2024-04-16T16:35:50.556Z"}
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
409
application/json
string
PUT
/api/v1/advertisements
(allows you to create an advert)
name type data type advertId required uuid description required string price required int
http code content-type response 200
application/json
{ "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "title": "string", "description": "string", "price": 0, "images": [ "string" ], "categoryId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "typeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "addressId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "informationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "created": "2024-04-16T16:35:50.556Z", "updated": "2024-04-16T16:35:50.556Z"}
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
GET
/api/v1/advertisements
(allows you to get all adverts)
name type data type CategoryId not required uuid TypeId not required uuid OwnerId not required uuid SortOrderAsc not required boolean City not required string SortBy not required string PageNumber not required int32 PageSize not required int32
http code content-type response 200
application/json
{"items": [ { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "title": "string", "description": "string", "price": 0, "images": [ "string" ], "categoryId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "typeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "addressId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "informationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "created": "2024-04-16T16:43:32.440Z", "updated": "2024-04-16T16:43:32.440Z"} ], "pageNumber": 0, "totalPages": 0, "totalItemsCount": 0 }
GET
/api/v1/advertisements{ advertId:uiid }
(allows you to get one advert)
http code content-type response 200
application/json
{ "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "title": "string", "description": "string", "price": 0, "images": [ "string" ], "categoryId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "typeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "addressId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "informationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "created": "2024-04-16T16:35:50.556Z", "updated": "2024-04-16T16:35:50.556Z"}
404
application/json
string
PUT
/api/v1/advertisements/{ advertisementId:uuid }
(allows you to delete your advert)
http code content-type response 204
application/json
No Content
401
application/json
string
403
application/json
string
404
application/json
string
Each User can add an address to their adverts
POST
/api/v1/addresses
(allows you to add address data for advert)
name type data type advertId required uuid city required string street required string province required string house required string gpsPosition required string
http code content-type response 201
application/json
{"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "advertId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "city": "string", "street": "string", "province": "string", "house": "string", "gpsPosition": "string"}
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
409
application/json
string
PUT
/api/v1/addresses
(allows you to update address data for advert)
name type data type advertId required uuid city required string street required string province required string house required string gpsPosition required string
http code content-type response 201
application/json
{"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "advertId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "city": "string", "street": "string", "province": "string", "house": "string", "gpsPosition": "string"}
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
GET
/api/v1/address/{ addressId:uuid }
(allows you to return address data)
http code content-type response 200
application/json
{"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "advertId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "city": "string", "street": "string", "province": "string", "house": "string", "gpsPosition": "string"}
404
application/json
string
Each user can add detailed information to their advert
POST
/api/v1/information
(allows you to add information for advert)
name type data type advertId required uuid roomCount required int area required int floor required int elevator required boolean balcony required boolean yearOfConstruction required string energyEfficiencyRating required string
http code content-type response 201
application/json
{"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "advertId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "roomCount": 0, "area": 0, "yearOfConstruction": 2025, "elevator": true, "balcony": true, "floor": 0, "energyEfficiencyRating": "string"}
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
409
application/json
string
PUT
/api/v1/information
(allows to update information for advert)
name type data type informationId required uuid roomCount not required int floor not required int yearOfConstruction not required string energyEfficiencyRating not required string elevator not required boolean balcony not required boolean
http code content-type response 200
application/json
{"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "dateOfBirth": "2024-04-16"}
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
GET
/api/v1/information/{ informationId:uuid }
(allows you to return information for advert)
http code content-type response 200
application/json
{"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string", "firstName": "string", "lastName": "string", "phone": "string", "dateOfBirth": "2024-04-16"}
404
application/json
string
Each User can get a list of available categories (house, apartment, etc.)
GET
/api/v1/categories
(allows you to return all categories)
http code content-type response 200
application/json
[ { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "description": "string" } ]
Each user can get a list of available types (buy, rent and so on)
GET
/api/v1/types
(allows you to return all types)
http code content-type response 200
application/json
[ { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string" } ]
Each user creating an advert can upload up to 5 images for each advert. This user can also update and delete them
POST
/api/v1/files/upload-image/{ advertId:uuid }
(allows you to upload images to you adverts)
name type data type file required image/png
http code content-type response 200
application/json
"string"
401
application/json
"string"
403
application/json
"string"
404
application/json
"string"
409
application/json
"string"
GET
/api/v1/files/download-image/{ advertId:uuid }/{ imageName:string }
(allows you to download images to you adverts)
http code content-type response 200
multipart/form-data
"immage/png"
404
application/json
"string"
DELETE
/api/v1/files/delete-image/{ advertId:uuid }/{ imageName:uuid }
(allows you to delete your images)
http code content-type response 204
application/json
No Content
401
application/json
string
403
application/json
string
404
application/json
string