A REST API built using ASP.NET Core, EF Core, PostgreSQL, AWS, Clean Architecture, DDD, CQRS, and other technologies. This project exemplifies top coding standards, providing a neat, effective, and scalable solution.
👉 This project was developed for educational purposes, but feel free to use it as a reference or for any other purpose.
Eventify is a simple event platform where producers can create and manage events, and attendees can search for events and book tickets.
Some cool features you will discover here:
- Clean Architecture: The project follows the principles of Clean Architecture, which emphasize separating concerns and defining clear responsibilities.
- DDD: A software design approach that prioritizes the problem domain over technology, aiming to develop systems that align with the language and requirements of the business.
- CQRS: An architectural pattern that separates the read and update operations of a data store (in this project, encouraged more as a code style, as we use a single database).
- API Versioning: The project adopts versioning to facilitate progressive changes while maintaining backward compatibility.
- API Rate Limiting: The project adopts rate limiting to prevent request abuses.
- Authentication and Authorization: The project implements authentication and authorization with JWT.
- Unit Testing: The solution includes individual test projects for unit testing the API layers.
- Database Transactions: The project supports database transactions. Each command that implements the ITransactional interface is executed in a single transaction.
- Pipeline Behaviors: The project implements various Pipeline Behaviors for managing Authorization, Exceptions, Logging, Transactions, and Validations.
The project follows the Clean Architecture principles inspired by Jason Taylor's Clean Architecture Solution Template, with some modifications to suit my preferences and needs.
To successfully build and run this project, you will need the following tools properly configured:
ℹ️ In the /aws
directory, you will find the cognito-functions
sln with a Lambda Function
implementation to handle the
AWS
Cognito Pre Sign-Up
event.
This Lambda Function is used to automatically confirm the user during registration. Build and deploy this Lambda
function to AWS and configure Cognito to trigger it.
Otherwise, manual user confirmation will be required. Also, create the user groups attendee
and producer
to manage
user roles in the system.
- Clone the repository
git clone https://github.com/pedrior/eventify-api.git
cd eventify-api
- Configure the required application settings
{
"ConnectionStrings": {
"DefaultConnection": "Your PostgreSQL connection string (Skip if you're using Docker Compose)"
},
"AWS": {
"Region": "Your AWS Region",
"UserPoolClientId": "Your AWS Cognito User Pool Client Id",
"UserPoolClientSecret": "Your AWS Cognito User Pool Client Secret",
"UserPoolId": "Your AWS Cognito User Pool Id"
},
"Storage": {
"Bucket": "Your S3 Bucket Name"
}
}
⚠️ Make sure you have configured the AWS credentials in the environment variables.
See Environment variables to configure the AWS CL for further details.
- Create a certificate for the API to run on Docker over HTTPS
dotnet dev-certs https -ep $env:USERPROFILE\.aspnet\https\Eventify.Presentation.pfx -p password
dotnet dev-certs https --trust
⚠️ Make sure that the certificate name and password match those specified in thedocker-compose.yml
file.
See Developing ASP.NET Core Applications with Docker over HTTPS for further details.
- Create and apply the database migration
ℹ️ In this step, you need to have the database running for the migration to be successful.
dotnet ef migrations add Initial -s src/Eventify.Presentation -p src/Eventify.Infrastructure -o ./Common/Persistence/Migrations
dotnet ef database update -s src/Eventify.Presentation -p src/Eventify.Infrastructure
- Run with Docker Compose
docker compose up --build
The API offers endpoints for handling events, tickets, bookings, and users. You can locate all *.http
samples in the
src/Eventify.Presentation/Requests directory
, and execute them using any REST client.
Location
The API is available at https://localhost:8081/api/{version}
.
Versioning
The API is versioned through the URL path. By default, all endpoints use the v1
version of the API.
Authorization
The API uses JWT Bearer Authentication for endpoint protection. When making authenticated requests, you need to
include the access token in the Authorization
header with the Bearer
scheme.
ℹ️ You can obtain an
access_token
by sending a request to the/v1/account/login
endpoint.
If you fail to provide the access token or provide an invalid one, you will get a 401 Unauthorized
response. If you
provide a valid access token but lack authorization for the request, you will receive a 403 Forbidden
response.
Authorization: Bearer {access_token}
Rate Limiting:
Most endpoints have rate limits to prevent abuse. If you surpass the request limit within a specific time frame, you
will get a 429 Too Many Requests
response.
Responses
The API uses standard HTTP response codes to indicate the success or failure of an API request.
Code | Description |
---|---|
200 - OK | Everything worked as expected. |
201 - Created | Everything worked as expected, and as result, has created a new resource. |
204 - No Content | Everything worked as expected, but is not going to return any content. |
400 - Bad Request | The request was unacceptable, often due to missing a required parameter or malformed parameter. |
401 - Unauthorized | The request requires user authentication. |
403 - Forbidden | The user is authenticated but not authorized to perform the request. |
404 - Not Found | The requested resource doesn’t exist. |
409 - Conflict | The request could not be completed due to a conflict with the current state of the resource. |
422 - Unprocessable Entity | The request body was acceptable but unable to be processed, often due to business logic errors. |
429 - Too Many Requests | Too many requests hit the API too quickly. |
500 - Internal Server Error | An unexpected error occurred. |
Errors
The API provides error responses compliant with RFC 7807. The response may contain additional fields to provide a more detailed description of the error.
Examples:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.10",
"title": "Conflict",
"status": 409,
"traceId": "00-9544cfe6df9d42a0553f910ca6d228b7-6469fbed19a87208-00",
"errors": [
{
"code": "event.slug_already_exists",
"message": "The slug is already associated with another event",
"details": {
"slug": "awesome-event-slug"
}
}
]
}
Validation errors:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"slug": [
"Must not be empty.",
"Must contain only lowercase letters, numbers, dashes and must not start or end with a dash."
]
},
"traceId": "00-3d6a0b01f3384b9327b7de83c37c8005-792cece6737ab181-00"
}
This project is licensed under the terms of the MIT license.