The EventManager
is a software engineering project of HTL Villach's 5AHITS (Year 2024/2025) that provides a management tool for concerts and other kinds of events.
This section covers all important point about provisioning and testing the EventManager
.
- Ubuntu 24.04 Server (recommended)
- Docker Runtime (more security with Docker Rootless)
- Source code of the Github repository
- Clone the source code from GitHub
git clone https://github.com/zVSciy/EventManager.git
- Run the stack using
docker-compose-test.yaml
docker compose -f docker-compose-test.yaml up [parameters]
- Wait until every container is started and all databases as well as APIs are healthy. After the integration tests had run (exit with code 0), the
EventManager
may be used by opening the websitehttps://<server-ip>:8080/
If you are not familiar with Docker, here are some parameters that might be helpful.
- -d → Detached mode; Output of containers is not shown in the command line which causes the CLI to be further accessible.
- --build → All containers, including their environments, are rebuild.
To start off, if you have not installed the Docker Runtime yet, mind Docker's installation guide: https://docs.docker.com/engine/install/ubuntu/
The following commands for rootless Docker originate from Docker's official documentation, see: https://docs.docker.com/engine/security/rootless/#install. Keep in mind that the given commands should be executed with the user that is responsible for Docker later on.
- Install
uidmap
sudo apt-get install -y uidmap
- Shutdown Docker's system deamon
sudo systemctl disable --now docker.service docker.socket
- Install
Dockerd-Rootless-Setup
dockerd-rootless-setuptool.sh install
- Define the variable
DOCKER_HOST
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
The Docker engine is now placed in the current user's directory which means that the Docker runtime uses user permissions instead of root
ones. As a result, the docker commands do not require sudo
anymore when using a simple user.
- Each service runs its Unittest automatically when started.
- Integration tests are defined in
./Integration_Tests
. - The NGINX proxy resolves the following services:
- User Management →
/
- Event →
/app_event
- Ticket →
/app_ticket
- Notification →
/app_notification
- Review →
/app_review
- User Management →
- The
Payment
service has not been integrated into other components as it was submitted way too late.
In the following, the process and concept of this application is introduced.
The project consists of the following six microservices:
- User (User management)
- Event
- Ticket
- Payment
- Notification
- Review (Feedback)
Each one fulfills crucial functionalities that are combined in order to achieve overall functionality of the EventManager
.
A short documentation of the API endpoint of each service is stated below.
GET /event/
GET /event/<event-id>
Response
{
"code": 200,
"reponse": [
{
"ID": 1,
"name": "Markforster Konzert",
"location": "Ruine Landskron",
"organisator": "Gemeinde Finkenstein",
"startdate": "2024-09-29T20:00:00Z",
"available_normal_tickets": 100,
"available_vip_tickets": 20,
"canceled": false
},
{
"ID": 2,
"name": "Ramstein Konzert",
"location": "Klagenfurter Stadion",
"organisator": "Klagenfurter Konzertverein",
"startdate": "2024-08-29T22:10:00Z",
"available_normal_tickets": 2000,
"available_vip_tickets": 200,
"canceled": false
}
],
}
GET /event/available_tickets/<event-id>
{
"code": 200,
"reponse": [
{
"ID": 1,
"available_normal_tickets": 100,
"available_vip_tickets": 20,
}
],
}
POST /event/
Payload
{
"name": "Markforster Konzert",
"location": "Ruine Landskron",
"organisator": "Gemeinde Finkenstein",
"startdate": "2024-09-29T20:00:00Z",
"available_normal_tickets": 100,
"available_vip_tickets": 20,
}
Response
{
"code": 200,
"reponse": "Event was created successfully"
"eventID": 1
}
PUT /event/<event-id>/
Payload
{
"name": "Bla Konzert",
"location": "Ruine Finkenstein",
"organisator": "Gemeinde Finkenstein",
"startdate": "2024-09-29T20:00:00Z",
"available_normal_tickets": 10,
"available_vip_tickets": 50,
}
Response
{
"code": 200,
"reponse": "Event was updated successfully"
"eventID": 1
}
PUT /event/cancel/<event-id>
Payload
{
"canceled": true
}
Response
{
"code": 200,
"reponse": "Event was canceled successfully"
"eventID": 1
}
PUT /event/updateTicket/
Payload
{
"available_normal_tickets": 20
"abailable_vip_tickets": 5
}
Response
{
"code": 200,
"reponse": "Available tickets were updated successfully"
"eventID": 1
}
ID INT AUTO_INCREMENT PRIMARY KEY
Name VARCHAR
Location VARCHAR
Organisator VARCHAR
StartDate DateTime
Available_normal_tickets INT
Available_vip_tickets INT
Canceled BOOLEAN Default False
Needs to know if the user is admin or not.
GET /ticket/
GET /ticket/<ticket-id>
Reponse:
{
"code": 200,
"reponse": [
{
"row": "A",
"price": 12.99,
"seatNumber": 3,
"state": "paid",
"vip": true,
"user": 1,
"event": 1
},
{
"row": "A",
"price": 12.99,
"seatNumber": 4,
"state": "paid",
"vip": true,
"user": 1,
"event": 1
}
],
}
POST /ticket
Payload:
{
"row": "A",
"price": 12.99,
"seatNumber": 3,
"state": "awaiting payment",
"vip": true,
"user": 1,
"event": 1
}
Reponse:
{
"code": 201,
"reponse": "Successfully created object!",
"createdId": 1
}
PUT /ticket/<ticket-id>
Payload:
{
"row": "A",
"price": 12.99,
"seatNumber": 3,
"state": "paid",
"vip": true,
"user": 1,
"event": 1
}
Reponse:
{
"code": 200,
"reponse": "Successfully updated object!",
"affectedId": 1
}
ID INT PRIMARY KEY
Row VARCHAR NULL
Price INT
SeatNumber INT NULL
State VARCHAR
VIP BOOLEAN
User INT (References to User.id)
Event INT (References to Event.id)
Needs Data from Event- and Userservice
Request:
{
"skip":0,
"limit":10,
}
skip and limit is optional, default is listed above
Response:
[
{
"id": 1,
"timestamp": 1729235305,
"paymentId": 2,
"eventId": 1,
"description": "testdesc",
"userId":2,
"status": "active",
"ticketId": 4
},
{
"id": 2,
"timestamp": 1729235305,
"paymentId": 2,
"eventId": 1,
"description": "testdesc",
"userId":2,
"status": "active",
"ticketId": 4
},
{
"id": 3,
"timestamp": 1729235305,
"paymentId": 2,
"eventId": 1,
"description": "testdesc",
"userId":2,
"status": "active",
"ticketId": 4
}
]
Response:
{
"id": 2,
"timestamp": 1729235305,
"paymentId": 2,
"eventId": 1,
"description": "testdesc",
"userId":2,
"status": "active",
"ticketId": 4
}
Request:
{
"description": "testdesc",
"status": "active",
"timestamp": "2024-02-17T00:15:05",
"eventId": "1",
"paymentId": "2",
"ticketId": "4",
"userId":2,
}
Note the timestamp is in seconds, the example timestamp is somewhere around 12:00 04.10.2024
Response:
{
"id": 3,
"timestamp": 1729235305,
"paymentId": 2,
"eventId": 1,
"description": "testdesc",
"userId":2,
"status": "active",
"ticketId": 4
}
Request:
{
"timestamp": 123213,
"paymentId": 2,
"userId": 2,
"eventId": 5,
"description": "edited",
"status": "disabled",
"ticketId": 45
}
Note the timestamp is in seconds, the example timestamp is somewhere around 12:00 04.10.2024
Response:
{
"id": 2,
"timestamp": 123213,
"paymentId": 2,
"userId": 2,
"eventId": 5,
"description": "edited",
"status": "disabled",
"ticketId": 45
}
id INT PRIMARY KEY AUTO INCREMENT
status VARCHAR
description Text
timestamp int
userId INT (References to User.Id)
eventId INT (References to Event.Id)
paymentId INT (References to Payment.Id)
ticketId INT (References to Ticket.Id)
Needs Data from Ticket-, Event- and Paymentservice
Response:
{
"content": "Great event!",
"event_id": 1,
"rating": 5,
"user_id": 1,
"id": 1
}
Response:
[
{
"event_id": 1,
"content": "Great event!",
"rating": 5,
"user_id": 1,
"id": 1
},
{
"event_id": 2,
"content": "Not bad",
"rating": 3,
"user_id": 2,
"id": 2
},
{
"event_id": 1,
"content": "Could be better",
"rating": 2,
"user_id": 3,
"id": 3
},
{
"event_id": 2,
"content": "Loved it!",
"rating": 5,
"user_id": 4,
"id": 4
}
]
Response:
[
{
"event_id": 3,
"content": "Terrible experience",
"rating": 1,
"user_id": 6,
"id": 6
},
{
"event_id": 3,
"content": "Pretty good",
"rating": 4,
"user_id": 7,
"id": 7
}
]
Request:
{
"user_id": 4,
"content": "Amazing event!",
"rating": 5,
"event_id": 1
}
Response:
{
"event_id": 1,
"content": "Amazing event!",
"rating": 5,
"user_id": 4,
"id": 10
}
Request:
{
"user_id": 4,
"content": "Shit event!!!",
"rating": 1,
"event_id": 1
}
Response:
{
"event_id": 1,
"content": "Shit event!!!",
"rating": 1,
"user_id": 4,
"id": 10
}
Response:
{
"detail": "Review deleted successfully"
}
- ID INT PRIMARY KEY
- User INT
- Comment Text
- Rating INT
- Event INT
Needs Data from Ticket-, Event- and Userservice.
/create
/update
/read
(/delete)
ID INT PRIMARY KEY
Firstname VARCHAR
Lastname VARCHAR
Email VARCHAR