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.
👷 Frameworks, Libraries and Technologies
🐳 List of docker containers
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
Swagger UI
http://localhost:5000/swagger/index.html
Swagger static file
https://github.com/gitEugeneL/RightPlace/blob/main/swagger.json
🔧 Implementation features
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
email
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
email
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 all users (🔒️jwt required )
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 one user (🔒️jwt required )
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
Update your account (🔒️jwt required )
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 your account (🔒️jwt required )
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
Create new advert (🔒️jwt required )
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
Update you advert (🔒️jwt required )
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
Delete your advert (🔒️jwt required )
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
Add address data for advert (🔒️jwt required )
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
Update address data for advert (🔒️jwt required )
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
Add information for advert (🔒️jwt required )
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
Update your advert information (🔒️jwt required )
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
Upload images (🔒️jwt required )
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 your images (🔒️jwt required )
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