Skip to content

Commit d5c89b9

Browse files
authored
Merge pull request #7 from Faculty-Projects-Organisation/develop
Some QoL impovements to the repo
2 parents 0fbab3f + 184c0fb commit d5c89b9

37 files changed

+551
-1050
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Build and Push Docker DEV Image
2+
3+
on:
4+
push:
5+
branches:
6+
- develop
7+
8+
jobs:
9+
build-and-push:
10+
name: Push Docker DEV image to Docker Hub
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout repository
14+
uses: actions/checkout@v3
15+
16+
- name: Login to Docker Hub
17+
uses: docker/login-action@v2
18+
with:
19+
username: ${{ secrets.DOCKERHUB_USERNAME }}
20+
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }}
21+
- name: Build and push Docker image
22+
uses: docker/build-push-action@v4
23+
with:
24+
context: RSOUserMicroServiceAPI/
25+
push: true
26+
tags: muchacho3alex/rsouserservice:dev
27+
file: RSOUserMicroServiceAPI/RSOUserMicroService/Dockerfile

Exercises.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Exercises
2+
3+
## Exercise 1: Docker Image Preparation
4+
In this exercise, you will optimize your application's Docker image by organizing it into multiple layers. This involves separating dependencies (libraries) that rarely change into lower layers, while placing your application code in higher layers. You'll then set up continuous integration (CI) using GitHub Actions or another preferred service to automate the build process. This CI/CD pipeline should compile and package all code from the main branch, create a new Docker image with the appropriate tag, and publish the image to a Docker Hub repository.
5+
6+
## Kubernetes
7+
Securely storing sensitive information like database connection passwords is crucial in Kubernetes. In this exercise, you'll learn how to manage secrets by storing the database connection password in a secret object within Kubernetes. This ensures that sensitive information is kept safe and can be accessed securely by your microservices.
8+
9+
## Exercise 2: Configuration Management
10+
Effective configuration management is essential for modern microservice architectures. You'll explore concepts such as using environment variables for configuration and separating configuration from code. By defining configuration settings that can be easily changed without recompiling or reinstalling the microservice, you'll ensure flexibility and maintainability in your application.
11+
12+
## Exercise 3: Health Check API and Kubernetes Liveness Probes
13+
Ensuring the health of your microservices is critical for maintaining system reliability and availability. You'll implement a Health Check API within your services to monitor their health status. Additionally, you'll leverage Kubernetes Liveness Probes to automatically detect and restart unhealthy service instances. This exercise will help you build robust, self-healing microservices that can recover from failures gracefully.
14+
15+
## Exercise 4: Metrics Collection
16+
Collecting and analyzing metrics is essential for gaining insights into the performance and behavior of your microservices. You'll add endpoints to expose metrics such as request latency, error rates, and resource utilization. By utilizing tools like KumuluzEE Metrics or Datadog, you'll be able to collect and visualize these metrics, enabling you to monitor and optimize your Kubernetes environment effectively.
17+
18+
## Exercise 5: Kubernetes Logs
19+
Logging is crucial for troubleshooting and debugging microservices deployed in Kubernetes. You'll explore Kubernetes logging mechanisms and implement centralized logging for your microservices. By configuring your microservices to send logs to a centralized logging system, such as logit.io, you'll be able to aggregate and analyze logs from multiple service instances, making it easier to identify and resolve issues.
20+
21+
## Exercise 6: API Documentation with OpenAPI
22+
Documenting your REST APIs is essential for ensuring interoperability and facilitating collaboration between teams. You'll use OpenAPI specifications to document your APIs, including details such as endpoints, request/response formats, and authentication mechanisms. Additionally, you'll provide a graphical interface for exploring and interacting with your APIs, making it easier for developers to understand and use your services.
23+
24+
## External API Integration
25+
Incorporating external APIs into your application can extend its functionality and provide access to valuable third-party services. You'll integrate an external API into your microservice application, leveraging tools like RapidAPI to discover and consume APIs. This exercise will give you hands-on experience with integrating external services and handling API requests and responses within your application.
26+
27+
## Advanced Communication Protocol (Optional)
28+
Implementing asynchronous communication protocols can improve the scalability and resilience of your microservice architecture. In this optional exercise, you'll explore asynchronous REST calls and integrate them into your microservice application. By decoupling services and leveraging asynchronous messaging patterns, you'll be able to handle high loads and improve fault tolerance in your application.
29+
Don't forget to prepare a simple user interface (web and/or mobile) for your application. The user interface should include a few simple screens that demonstrate the functionality of your application (e.g., uploading images, viewing all user images, displaying one image along with comments, etc.). The user interface should be straightforward, with a focus on showcasing the implemented functionalities of your microservice application.
30+
31+
## Exercise 7: Ingress
32+
33+
Configure an ingress proxy on Kubernetes so that all your microservices are publicly accessible through a single address. You can use the ingress installed on your cloud provider or install any ingress controller, such as NGINX Ingress Controller.
34+
35+
Useful resources:
36+
- [Ingress Controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/)
37+
- [Ingress on Azure](https://docs.microsoft.com/en-us/azure/aks/ingress-basic)
38+
- [NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/)
39+
40+
## Exercise 8: Fault Isolation and Tolerance
41+
42+
Simulate an error in one of the calls between two microservices (e.g., the microservice registers at the wrong address or port, the microservice returns improperly formatted data, etc.). The goal of this task is to limit the impact of errors in individual microservices on the entire application.
43+
44+
You can use KumuluzEE Fault Tolerance to assist in implementing fault resilience. Prepare an appropriate fallback mechanism that will trigger in case of an error in the called microservice. You can use a timer (timeout) in implementing fault resilience. Implement a circuit breaker. Prepare a demonstration showing different states of the circuit breaker (open, half-open, closed).
45+
46+
Simulate an error again in one of the microservices and observe the application's behavior.
47+
48+
## Exercise 9: Advanced Communication Protocol
49+
50+
Incorporate the GraphQL protocol into your microservice application.
51+
52+
## Optional Task (Exercise 9)
53+
54+
### Stream Processing Systems
55+
56+
Apache Kafka is a stream-processing platform that enables the processing, storing, creation, and reading of events. Support event-driven interaction in your project and sensibly incorporate a stream processing system that allows publishing and subscribing to event streams. Examples of events include IoT device sensor readings, orders, and transactions. Create a single topic, where the producer inserts records into the topic, and the consumer reads records from partitions. You can use KumuluzEE Event Streaming, which supports the Apache Kafka platform. This task earns additional points.
57+
58+
You can find resources on:
59+
- [KumuluzEE Event Streaming](https://docs.kumuluz.com/event-streaming/master/)
60+
- [Apache Kafka](https://kafka.apache.org/)
61+
62+
## Optional Task (Exercise 10)
63+
64+
### Advanced Communication Protocol
65+
66+
Incorporate the gRPC protocol into your micr

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# User Microservice In ASP .NET 8 [Cloud computing @ FRI UL]
2+
3+
![Build Status](https://img.shields.io/badge/Build-Passing-brightgreen)
4+
5+
A microservice dedicated to handling user CRUD operations for the advertisement web app "Oglasnik" which serves as the project for the course cloud computing.
6+
7+
## Contributors
8+
- [Aleksander Kovač](https://github.com/shanji97)
9+
- [Urbanus98](https://github.com/urbanus98)
10+
11+
## Docker
12+
[![Docker Hub](https://img.shields.io/badge/Build-Passing-brightgreen)](https://hub.docker.com/r/muchacho3alex/rsouserservice/tags)
13+
14+
## Related Repositories
15+
[![rso-ad-service](https://img.shields.io/badge/GitHub-rso--ad--service-blue)](https://github.com/Faculty-Projects-Organisation/rso-ad-service)
16+
[![rso-discussions-service](https://img.shields.io/badge/GitHub-rso--discussions--service-blue)](https://github.com/Faculty-Projects-Organisation/rso-discussions-service)
17+
[![rso-transaction-service](https://img.shields.io/badge/GitHub-rso--transaction--service-blue)](https://github.com/Faculty-Projects-Organisation/rso-transaction-service)
18+
[![kubernetes](https://img.shields.io/badge/GitHub-kubernetes-blue)](https://github.com/Faculty-Projects-Organisation/kubernetes)
19+
20+
## Exercises
21+
For detailed explanations of each exercise that culminated in this project, refer to the [Exercises.md](Exercises.md) file.
22+
23+
## LinkedIn
24+
[![LinkedIn](https://img.shields.io/badge/LinkedIn-Profile-blue)](https://www.linkedin.com/in/aleksander-kova%C4%8D-0662a8156/)

RSOUserMicroServiceAPI/RSO.Core/BL/IUserLogic.cs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,30 @@
44
namespace RSO.Core.BL;
55

66
/// <summary>
7-
/// Handles the user logic.
7+
/// Handles the userId logic.
88
/// </summary>
99
public interface IUserLogic
1010
{
1111
/// <summary>
12-
/// Deletes the user.
12+
/// Gets the city name from the userId zip code.
1313
/// </summary>
14-
/// <param name="user">The user we would like to delete.</param>
15-
/// <returns>Throw error if it fails.</returns>
16-
public Task DeleteUserAsync(User user);
14+
/// <param name="userZipCode">The userId provided zip code.</param>
15+
/// <returns>The name of the city.</returns>
16+
public Task<string?> GetCityFromZipCodeAsync(string userZipCode);
1717

1818
/// <summary>
19-
/// Gets the city name from the user zip code.
19+
/// Deletes the userId.
2020
/// </summary>
21-
/// <param name="userZipCode">The user provided zip code.</param>
22-
/// <returns>The name of the city.</returns>
23-
public Task<string> GetCityFromZipCodeAsync(string userZipCode);
21+
/// <param name="userId">The userId we would like to delete.</param>
22+
/// <returns>Throw error if it fails.</returns>
23+
public Task<bool> DeleteUserAsync(int userId);
2424

2525
/// <summary>
2626
/// Gets the JWT.
2727
/// </summary>
28-
/// <param name="existingUser">The user that hopefully exist in our database.</param>
28+
/// <param name="existingUser">The userId that hopefully exist in our database.</param>
2929
/// <returns>JWT token if result is true.</returns>
30-
public string GetJwtToken(User existingUser);
30+
public string? GetJwtToken(User existingUser);
3131

3232
/// <summary>
3333
/// Gets all users.
@@ -36,26 +36,26 @@ public interface IUserLogic
3636
public Task<List<User>> GetAllUsersAsync();
3737

3838
/// <summary>
39-
/// Gets user by its Id.
39+
/// Gets userId by its Id.
4040
/// </summary>
41-
/// <param name="id">The userId of the user.</param>
42-
/// <returns><see cref="User"/> instance, specified by the userId of the user.</returns>
41+
/// <param name="id">The userId of the userId.</param>
42+
/// <returns><see cref="User"/> instance, specified by the userId of the userId.</returns>
4343
public Task<User> GetUserByIdAsync(int id);
4444

4545
/// <summary>
46-
/// Gets the user based on the provided username or email or password.
46+
/// Gets the userId based on the provided username or email or password.
4747
/// </summary>
48-
/// <param name="emailOrUsername"></param>
49-
/// <param name="password"></param>
50-
/// <returns>The user specified by the email or username and password.</returns>
51-
public Task<User> GetUserByUsernameOrEmailAndPasswordAsync(string emailOrUsername, string password);
48+
/// <param name="emailOrUsername">User's email or username.</param>
49+
/// <param name="password">User's password.</param>
50+
/// <returns>The userId specified by the email or username and password.</returns>
51+
public User GetUserByUsernameOrEmailAndPassword(string emailOrUsername, string password);
5252

5353
/// <summary>
54-
/// Get ads from a certain user.
54+
/// Get ads from a certain userId.
5555
/// </summary>
56-
/// <param name="userId"></param>
57-
/// <returns></returns>
58-
public Task<List<Ad>> GetUsersAdsAsync(int userId);
56+
/// <param name="userId">The id of the userId for which the adds are going to be queried.</param>
57+
/// <returns>A list of userId's advertisements based on the userId's id.</returns>
58+
public Task<List<Ad>?> GetUsersAdsAsync(int userId);
5959

6060
/// <summary>
6161
/// Checks if the email is unique.
@@ -72,36 +72,36 @@ public interface IUserLogic
7272
public Task<bool> IsUserNameUniqueAsync(string userName);
7373

7474
/// <summary>
75-
/// Implements user registration and insert the user.
75+
/// Implements userId registration and insert the userId.
7676
/// </summary>
7777
/// <param name="newUser"></param>
7878
/// <returns>The same <see cref="User"/> object with and userId.</returns>
7979
public Task<User> RegisterUserAsync(User newUser);
8080

8181
/// <summary>
82-
/// Updates the user.
82+
/// Updates the userId.
8383
/// </summary>
8484
/// <param name="user"><see cref="User"/> instance.</param>
8585
/// <returns>True, if the username was successfully updated.</returns>
8686
public Task<bool> UpdateUserAsync(User user);
8787

8888
/// <summary>
89-
/// Updates the user data.
89+
/// Updates the userId data.
9090
/// </summary>
91-
/// <param name="userData">The new user data.</param>
91+
/// <param name="userData">The new userId data.</param>
9292
/// <returns>True, if the update was successfull.</returns>
9393
public Task<bool> UpdateUserDataAsync(User userData);
9494

9595
/// <summary>
96-
/// Checks if the user exists by username or email or password.
96+
/// Checks if the userId exists by username or email or password.
9797
/// </summary>
9898
/// <param name="userName">Username.</param>
99-
/// <param name="email">The email of the user.</param>
99+
/// <param name="email">The email of the userId.</param>
100100
/// <returns>True, if the username is already taken.</returns>
101101
public Task<bool> UsernameOrEmailAlreadyTakenAsync(string userName, string email);
102102

103103
/// <summary>
104-
/// Gets all the add of a certain user.
104+
/// Gets all the add of a certain userId.
105105
/// </summary>
106106
/// <param name="userId">User's ID.</param>
107107
/// <returns>All of the users ads.</returns>
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using Newtonsoft.Json;
22

3-
namespace RSO.Core.BL.LogicModels;
3+
namespace RSO.Core.BL.LogicModels.DTO;
44

55
/// <summary>
66
/// Stores the Zip Code and City from Dejci's API.
@@ -11,11 +11,11 @@ public class CityData
1111
/// Zip Code.
1212
/// </summary>
1313
[JsonProperty("postnaStevilka")]
14-
public int CityZip { get; set;}
14+
public int ZipCode { get; set; }
1515

1616
/// <summary>
1717
/// The name of the city that corresponds to the zip code.
1818
/// </summary>
1919
[JsonProperty("kraj")]
20-
public string City { get; set;}
20+
public string? City { get; set; }
2121
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace RSO.Core.BL.LogicModels.DTO;
2+
3+
/// <summary>
4+
/// DTO for the login credentials.
5+
/// </summary>
6+
public class LoginCredentialsDTO
7+
{
8+
/// <summary>
9+
/// The login credential of the user - email or username.
10+
/// </summary>
11+
public string? EmailOrUsername { get; set; }
12+
13+
/// <summary>
14+
/// User's password.
15+
/// </summary>
16+
public string? Password { get; set; }
17+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using RSO.Core.AdModels;
2+
using RSO.Core.UserModels;
3+
4+
namespace RSO.Core.BL.LogicModels.DTO;
5+
6+
/// <summary>
7+
/// A custom DTO for returning the needed user data.
8+
/// </summary>
9+
/// <remarks>
10+
/// Get the neccessary data from the user.
11+
/// </remarks>
12+
/// <param name="user"><see cref=User""/> instance.</param>
13+
/// <param name="adsFromTheUser">Advertisements from the user.</param>
14+
public class UserDataDTO(User user, List<Ad>? adsFromTheUser)
15+
{
16+
/// <summary>
17+
/// The date the user was registered on.
18+
/// </summary>
19+
public string RegisteredOn { get; } = $"Registriran od {user.RegisteredOn.Value:dd.MM.yyyy at H:mm}";
20+
21+
/// <summary>
22+
/// The user id.
23+
/// </summary>
24+
public int Id { get; } = user.UserId;
25+
26+
/// <summary>
27+
/// The user name.
28+
/// </summary>
29+
public string UserName { get; } = user.UserName;
30+
31+
/// <summary>
32+
/// The email of the user.
33+
/// </summary>
34+
public string UserEmail { get; } = user.UserEmail;
35+
36+
/// <summary>
37+
/// The user location based on the zip code and the city.
38+
/// </summary>
39+
public string UserLocation { get; } = $"{user.UserZipCode} {user.UserCity}";
40+
41+
/// <summary>
42+
/// The ads that the user has.
43+
/// </summary>
44+
public List<Ad> Ads { get; } = adsFromTheUser ?? [];
45+
}

RSOUserMicroServiceAPI/RSO.Core/BL/LogicModels/LoginCredentials.cs

Lines changed: 0 additions & 7 deletions
This file was deleted.

RSOUserMicroServiceAPI/RSO.Core/BL/LogicModels/UserDataDTO.cs

Lines changed: 0 additions & 47 deletions
This file was deleted.

0 commit comments

Comments
 (0)