├── auth-service
├── src
│ ├── test
│ │ ├── resources
│ │ │ ├── application.yml
│ │ │ ├── bootstrap.yml
│ │ │ └── logback-test.xml
│ │ └── java
│ │ │ └── pl
│ │ │ └── kubaretip
│ │ │ └── authservice
│ │ │ ├── utils
│ │ │ ├── JacksonIgnoreWriteOnlyAccess.java
│ │ │ └── SpringSecurityWebTestConfig.java
│ │ │ └── mapper
│ │ │ └── UserMapperImplTest.java
│ └── main
│ │ ├── resources
│ │ ├── application.yml
│ │ ├── db
│ │ │ └── migration
│ │ │ │ ├── V1.0.4__insert_authority_records.sql
│ │ │ │ ├── V1.0.1__create_authority_table.sql
│ │ │ │ ├── V1.0.3__create_user_authority_table.sql
│ │ │ │ └── V1.0.2__create_user_table.sql
│ │ ├── bootstrap.yml
│ │ └── bootstrap-docker.yml
│ │ └── java
│ │ └── pl
│ │ └── kubaretip
│ │ └── authservice
│ │ ├── constants
│ │ ├── AuthorityConstants.java
│ │ └── ApplicationConstants.java
│ │ ├── security
│ │ ├── model
│ │ │ ├── AuthRequestModel.java
│ │ │ └── TokenResponse.java
│ │ ├── AuthenticationSuccessHandler.java
│ │ ├── JWTBuilder.java
│ │ ├── AuthenticationFailureHandler.java
│ │ ├── JWTAuthenticationFilter.java
│ │ └── UserDetailsServiceImpl.java
│ │ ├── exception
│ │ ├── controllerAdvice
│ │ │ ├── CustomExceptionHandler.java
│ │ │ └── ValidationExceptionHandler.java
│ │ └── InvalidAuthenticationRequestException.java
│ │ ├── repository
│ │ ├── AuthorityRepository.java
│ │ └── UserRepository.java
│ │ ├── AuthServiceApplication.java
│ │ ├── service
│ │ └── UserService.java
│ │ ├── config
│ │ ├── RabbitMQConfig.java
│ │ └── SecurityConfig.java
│ │ ├── domain
│ │ ├── Authority.java
│ │ └── User.java
│ │ ├── web
│ │ ├── model
│ │ │ └── ChangePassRequest.java
│ │ └── rest
│ │ │ ├── AuthorizationController.java
│ │ │ └── UserController.java
│ │ ├── mapper
│ │ └── UserMapper.java
│ │ └── messaging
│ │ └── sender
│ │ └── UserSender.java
├── Dockerfile
└── pom.xml
├── config-server
├── src
│ └── main
│ │ ├── resources
│ │ ├── application.yml
│ │ ├── bootstrap.yml
│ │ └── bootstrap-docker.yml
│ │ └── java
│ │ └── pl
│ │ └── kubaretip
│ │ └── configserver
│ │ └── ConfigServerApplication.java
├── Dockerfile
└── pom.xml
├── chat-service
├── src
│ ├── main
│ │ ├── resources
│ │ │ ├── application.yml
│ │ │ ├── bootstrap.yml
│ │ │ ├── db
│ │ │ │ └── migration
│ │ │ │ │ ├── V1.0.1__create_chat_profile_table.sql
│ │ │ │ │ ├── V1.0.3__create_friend_chat_table.sql
│ │ │ │ │ └── V1.0.2__create_friend_request_table.sql
│ │ │ └── bootstrap-docker.yml
│ │ └── java
│ │ │ └── pl
│ │ │ └── kubaretip
│ │ │ └── chatservice
│ │ │ ├── exception
│ │ │ └── handler
│ │ │ │ └── CustomExceptionsHandler.java
│ │ │ ├── dto
│ │ │ ├── FriendChatDTO.java
│ │ │ ├── ChatProfileDTO.java
│ │ │ ├── FriendRequestDTO.java
│ │ │ └── mapper
│ │ │ │ ├── ChatProfileMapper.java
│ │ │ │ ├── FriendChatMapper.java
│ │ │ │ └── FriendRequestMapper.java
│ │ │ ├── service
│ │ │ ├── ChatProfileService.java
│ │ │ ├── FriendChatService.java
│ │ │ ├── FriendRequestService.java
│ │ │ └── impl
│ │ │ │ ├── ChatProfileServiceImpl.java
│ │ │ │ ├── FriendChatServiceImpl.java
│ │ │ │ └── FriendRequestServiceImpl.java
│ │ │ ├── repository
│ │ │ ├── ChatProfileRepository.java
│ │ │ ├── FriendChatRepository.java
│ │ │ └── FriendRequestRepository.java
│ │ │ ├── util
│ │ │ └── DateUtils.java
│ │ │ ├── domain
│ │ │ ├── ChatProfile.java
│ │ │ ├── FriendChat.java
│ │ │ └── FriendRequest.java
│ │ │ ├── ChatServiceApplication.java
│ │ │ ├── messaging
│ │ │ ├── listener
│ │ │ │ └── RabbitNewUserListener.java
│ │ │ └── sender
│ │ │ │ └── DeleteMessagesSender.java
│ │ │ ├── config
│ │ │ ├── RabbitMQConfig.java
│ │ │ └── SecurityConfig.java
│ │ │ └── web
│ │ │ └── rest
│ │ │ ├── ChatProfileController.java
│ │ │ ├── FriendChatController.java
│ │ │ └── FriendRequestController.java
│ └── test
│ │ └── java
│ │ └── pl
│ │ └── kubaretip
│ │ └── chatservice
│ │ └── service
│ │ └── impl
│ │ ├── FriendChatServiceImplTest.java
│ │ └── ChatProfileServiceImplTest.java
├── Dockerfile
└── pom.xml
├── mail-service
├── src
│ └── main
│ │ ├── resources
│ │ ├── application.yml
│ │ ├── bootstrap.yml
│ │ └── bootstrap-docker.yml
│ │ └── java
│ │ └── pl
│ │ └── kubaretip
│ │ └── mailservice
│ │ ├── service
│ │ ├── SendMailService.java
│ │ └── impl
│ │ │ └── MailServiceImpl.java
│ │ ├── MailServiceApplication.java
│ │ ├── messaging
│ │ └── listener
│ │ │ └── RabbitUserActivationListener.java
│ │ └── config
│ │ ├── RabbitMQConfig.java
│ │ └── AsyncConfig.java
├── Dockerfile
└── pom.xml
├── eureka-server
├── src
│ └── main
│ │ ├── resources
│ │ ├── application.yml
│ │ ├── bootstrap.yml
│ │ └── bootstrap-docker.yml
│ │ └── java
│ │ └── pl
│ │ └── kubaretip
│ │ └── eurekaserver
│ │ └── EurekaServerApplication.java
├── Dockerfile
└── pom.xml
├── chat-messages-service
├── src
│ └── main
│ │ ├── resources
│ │ ├── application.yml
│ │ ├── bootstrap.yml
│ │ └── bootstrap-docker.yml
│ │ └── java
│ │ └── pl
│ │ └── kubaretip
│ │ └── chatmessagesservice
│ │ ├── constant
│ │ ├── MessageStatus.java
│ │ └── DateConstants.java
│ │ ├── ChatMessagesServiceApplication.java
│ │ ├── security
│ │ ├── SecurityUtils.java
│ │ ├── JWTAuthenticationManager.java
│ │ └── JWTAuthenticationConverter.java
│ │ ├── document
│ │ └── ChatMessage.java
│ │ ├── messaging
│ │ └── listener
│ │ │ ├── RabbitMessageDeletingListener.java
│ │ │ └── RabbitMessageStoringListener.java
│ │ ├── service
│ │ ├── ChatMessageService.java
│ │ └── impl
│ │ │ └── ChatMessageServiceImpl.java
│ │ ├── repository
│ │ └── ChatMessageRepository.java
│ │ ├── web
│ │ └── rest
│ │ │ └── ChatMessageController.java
│ │ └── config
│ │ ├── RabbitMQConfig.java
│ │ └── SecurityConfig.java
├── Dockerfile
└── pom.xml
├── cloud-gateway
├── src
│ └── main
│ │ ├── resources
│ │ ├── application.yml
│ │ ├── bootstrap.yml
│ │ └── bootstrap-docker.yml
│ │ └── java
│ │ └── pl
│ │ └── kubaretip
│ │ └── cloudgateway
│ │ ├── CloudGatewayApplication.java
│ │ └── config
│ │ ├── OpenAPIConfig.java
│ │ ├── CorsConfig.java
│ │ └── CloudConfig.java
├── Dockerfile
└── pom.xml
├── screenshot
└── diagram.png
├── messages-websocket-service
├── src
│ └── main
│ │ ├── resources
│ │ ├── application.yml
│ │ ├── bootstrap.yml
│ │ └── bootstrap-docker.yml
│ │ └── java
│ │ └── pl
│ │ └── kubaretip
│ │ └── messageswebsocketservice
│ │ ├── log
│ │ ├── WebSocketLogs.java
│ │ └── WebSocketConnectionListener.java
│ │ ├── MessagesWebSocketServiceApplication.java
│ │ ├── config
│ │ ├── RabbitMQConfig.java
│ │ ├── WebSocketSecurityConfig.java
│ │ ├── SecurityConfig.java
│ │ └── WebSocketConfig.java
│ │ ├── messaging
│ │ └── sender
│ │ │ └── StoringMessagesSender.java
│ │ ├── security
│ │ ├── WebSocketAuthService.java
│ │ └── AuthChannelInterceptor.java
│ │ └── web
│ │ └── websocket
│ │ └── MessagesController.java
├── Dockerfile
└── pom.xml
├── .circleci
└── config.yml
├── exception-utils
├── src
│ └── main
│ │ └── java
│ │ └── pl
│ │ └── kubaretip
│ │ └── exceptionutils
│ │ ├── NotFoundException.java
│ │ ├── InvalidDataException.java
│ │ ├── AlreadyExistsException.java
│ │ ├── error
│ │ ├── Violation.java
│ │ └── Error.java
│ │ └── CommonExceptionHandler.java
└── pom.xml
├── auth-utils
├── src
│ └── main
│ │ └── java
│ │ └── pl
│ │ └── kubaretip
│ │ └── authutils
│ │ ├── jwt
│ │ ├── JWTConstants.java
│ │ ├── JWTConfig.java
│ │ ├── JWTFilter.java
│ │ └── JWTUtils.java
│ │ ├── security
│ │ ├── SecurityUserDetails.java
│ │ └── SecurityUserDetailsImpl.java
│ │ └── SecurityUtils.java
└── pom.xml
├── docker
├── init-chat-messages-service-mongo.js
├── .env.dev
├── rabbitmq-isolated.conf
├── .env.docker
├── docker-compose-dev.yml
└── docker-compose-docker.yml
├── .gitignore
├── dto-models
├── src
│ └── main
│ │ └── java
│ │ └── pl
│ │ └── kubaretip
│ │ └── dtomodels
│ │ ├── ChatMessageDTO.java
│ │ └── UserDTO.java
└── pom.xml
└── README.md
/auth-service/src/test/resources/application.yml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/config-server/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8888
3 |
--------------------------------------------------------------------------------
/auth-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: auth
--------------------------------------------------------------------------------
/chat-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: chat
--------------------------------------------------------------------------------
/mail-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: mail
--------------------------------------------------------------------------------
/eureka-server/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: eureka
--------------------------------------------------------------------------------
/auth-service/src/test/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | enabled: false
--------------------------------------------------------------------------------
/chat-messages-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: chat-messages
--------------------------------------------------------------------------------
/cloud-gateway/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: cloud-gateway
4 |
5 |
--------------------------------------------------------------------------------
/screenshot/diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kubAretip/spring-micro-websocket-chat/HEAD/screenshot/diagram.png
--------------------------------------------------------------------------------
/cloud-gateway/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | uri: http://localhost:8888
--------------------------------------------------------------------------------
/eureka-server/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | uri: http://localhost:8888
--------------------------------------------------------------------------------
/messages-websocket-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: messages-websocket
--------------------------------------------------------------------------------
/auth-service/src/main/resources/db/migration/V1.0.4__insert_authority_records.sql:
--------------------------------------------------------------------------------
1 | insert into authority (name)
2 | VALUES ('ROLE_USER');
--------------------------------------------------------------------------------
/auth-service/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | name: commons, auth
5 | uri: http://localhost:8888
--------------------------------------------------------------------------------
/chat-service/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | name: commons, chat
5 | uri: http://localhost:8888
--------------------------------------------------------------------------------
/mail-service/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | name: commons, mail
5 | uri: http://localhost:8888
6 |
--------------------------------------------------------------------------------
/chat-messages-service/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | name: commons, chat-messages
5 | uri: http://localhost:8888
--------------------------------------------------------------------------------
/messages-websocket-service/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | name: commons, messages-websocket
5 | uri: http://localhost:8888
--------------------------------------------------------------------------------
/auth-service/src/main/resources/db/migration/V1.0.1__create_authority_table.sql:
--------------------------------------------------------------------------------
1 | create table if not exists authority
2 | (
3 | name varchar(50) not null unique primary key
4 | );
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/constants/AuthorityConstants.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.constants;
2 |
3 | public enum AuthorityConstants {
4 | ROLE_USER
5 | }
6 |
--------------------------------------------------------------------------------
/auth-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:11.0.2-jre-slim
2 | COPY target/auth-service-1.0-SNAPSHOT.jar .
3 | CMD /usr/bin/java -Dlogging.path=/log/ -Xmx400m -Xms400m -jar auth-service-1.0-SNAPSHOT.jar
4 | EXPOSE 8080
--------------------------------------------------------------------------------
/chat-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:11.0.2-jre-slim
2 | COPY target/chat-service-1.0-SNAPSHOT.jar .
3 | CMD /usr/bin/java -Dlogging.path=/log/ -Xmx400m -Xms400m -jar chat-service-1.0-SNAPSHOT.jar
4 | EXPOSE 8080
--------------------------------------------------------------------------------
/mail-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:11.0.2-jre-slim
2 | COPY target/mail-service-1.0-SNAPSHOT.jar .
3 | CMD /usr/bin/java -Dlogging.path=/log/ -Xmx400m -Xms400m -jar mail-service-1.0-SNAPSHOT.jar
4 | EXPOSE 8080
--------------------------------------------------------------------------------
/cloud-gateway/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:11.0.2-jre-slim
2 | COPY target/cloud-gateway-1.0-SNAPSHOT.jar .
3 | CMD /usr/bin/java -Dlogging.path=/log/ -Xmx400m -Xms400m -jar cloud-gateway-1.0-SNAPSHOT.jar
4 | EXPOSE 8080
--------------------------------------------------------------------------------
/config-server/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:11.0.2-jre-slim
2 | COPY target/config-server-1.0-SNAPSHOT.jar .
3 | CMD /usr/bin/java -Dlogging.path=/log/ -Xmx400m -Xms400m -jar config-server-1.0-SNAPSHOT.jar
4 | EXPOSE 8888
--------------------------------------------------------------------------------
/eureka-server/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:11.0.2-jre-slim
2 | COPY target/eureka-server-1.0-SNAPSHOT.jar .
3 | CMD /usr/bin/java -Dlogging.path=/log/ -Xmx400m -Xms400m -jar eureka-server-1.0-SNAPSHOT.jar
4 | EXPOSE 8761
--------------------------------------------------------------------------------
/chat-messages-service/src/main/java/pl/kubaretip/chatmessagesservice/constant/MessageStatus.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatmessagesservice.constant;
2 |
3 | public enum MessageStatus {
4 | RECEIVED, DELIVERED
5 | }
6 |
--------------------------------------------------------------------------------
/chat-messages-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:11.0.2-jre-slim
2 | COPY target/chat-messages-service-1.0-SNAPSHOT.jar .
3 | CMD /usr/bin/java -Dlogging.path=/log/ -Xmx400m -Xms400m -jar chat-messages-service-1.0-SNAPSHOT.jar
4 | EXPOSE 8080
--------------------------------------------------------------------------------
/messages-websocket-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:11.0.2-jre-slim
2 | COPY target/messages-websocket-service-1.0-SNAPSHOT.jar .
3 | CMD /usr/bin/java -Dlogging.path=/log/ -Xmx400m -Xms400m -jar messages-websocket-service-1.0-SNAPSHOT.jar
4 | EXPOSE 8080
--------------------------------------------------------------------------------
/chat-service/src/main/resources/db/migration/V1.0.1__create_chat_profile_table.sql:
--------------------------------------------------------------------------------
1 | create table if not exists chat_profile
2 | (
3 | user_id BINARY(16) not null unique primary key,
4 | friends_request_code varchar(64) not null unique
5 | )
--------------------------------------------------------------------------------
/auth-service/src/test/resources/logback-test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/eureka-server/src/main/resources/bootstrap-docker.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | uri: ${CLOUD_CONFIG_URI}
5 | fail-fast: true
6 | retry:
7 | max-attempts: 20
8 | initial-interval: 20000
9 | max-interval: 10000
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | orbs:
4 | maven: circleci/maven@1.1
5 |
6 | workflows:
7 | maven_test:
8 | jobs:
9 | - maven/test:
10 | filters:
11 | branches:
12 | only:
13 | - master
--------------------------------------------------------------------------------
/mail-service/src/main/java/pl/kubaretip/mailservice/service/SendMailService.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.mailservice.service;
2 |
3 | import pl.kubaretip.dtomodels.UserDTO;
4 |
5 | public interface SendMailService {
6 |
7 | void sendActivationEmail(UserDTO user);
8 | }
9 |
--------------------------------------------------------------------------------
/exception-utils/src/main/java/pl/kubaretip/exceptionutils/NotFoundException.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.exceptionutils;
2 |
3 | public class NotFoundException extends RuntimeException {
4 | public NotFoundException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/exception-utils/src/main/java/pl/kubaretip/exceptionutils/InvalidDataException.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.exceptionutils;
2 |
3 | public class InvalidDataException extends RuntimeException {
4 | public InvalidDataException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/exception-utils/src/main/java/pl/kubaretip/exceptionutils/AlreadyExistsException.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.exceptionutils;
2 |
3 | public class AlreadyExistsException extends RuntimeException {
4 | public AlreadyExistsException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/auth-service/src/main/resources/bootstrap-docker.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | name: commons, auth
5 | uri: ${CLOUD_CONFIG_URI}
6 | fail-fast: true
7 | retry:
8 | max-attempts: 20
9 | initial-interval: 60000
10 | max-interval: 10000
--------------------------------------------------------------------------------
/auth-utils/src/main/java/pl/kubaretip/authutils/jwt/JWTConstants.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authutils.jwt;
2 |
3 | public final class JWTConstants {
4 |
5 | public static final String AUTHORITIES_KEY = "roles";
6 | public static final String USERNAME_KEY = "preferred_username";
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/chat-service/src/main/resources/bootstrap-docker.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | name: commons, chat
5 | uri: ${CLOUD_CONFIG_URI}
6 | fail-fast: true
7 | retry:
8 | max-attempts: 20
9 | initial-interval: 60000
10 | max-interval: 30000
--------------------------------------------------------------------------------
/mail-service/src/main/resources/bootstrap-docker.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | name: commons, mail
5 | uri: ${CLOUD_CONFIG_URI}
6 | fail-fast: true
7 | retry:
8 | max-attempts: 20
9 | initial-interval: 60000
10 | max-interval: 30000
--------------------------------------------------------------------------------
/auth-utils/src/main/java/pl/kubaretip/authutils/security/SecurityUserDetails.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authutils.security;
2 |
3 | import org.springframework.security.core.userdetails.UserDetails;
4 |
5 | public interface SecurityUserDetails extends UserDetails {
6 |
7 | String getId();
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/chat-messages-service/src/main/resources/bootstrap-docker.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | name: commons, chat-messages
5 | uri: ${CLOUD_CONFIG_URI}
6 | fail-fast: true
7 | retry:
8 | max-attempts: 20
9 | initial-interval: 60000
10 | max-interval: 30000
--------------------------------------------------------------------------------
/messages-websocket-service/src/main/resources/bootstrap-docker.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | name: commons, messages-websocket
5 | uri: ${CLOUD_CONFIG_URI}
6 | fail-fast: true
7 | retry:
8 | max-attempts: 20
9 | initial-interval: 60000
10 | max-interval: 30000
--------------------------------------------------------------------------------
/chat-messages-service/src/main/java/pl/kubaretip/chatmessagesservice/constant/DateConstants.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatmessagesservice.constant;
2 |
3 | public final class DateConstants {
4 |
5 | public static final String UTC_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
6 |
7 | private DateConstants() {
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/docker/init-chat-messages-service-mongo.js:
--------------------------------------------------------------------------------
1 | db.createUser(
2 | {
3 | user : "chat-messages-service-user",
4 | pwd : "chat-messages-service-pass-123",
5 | roles : [
6 | {
7 | role: "readWrite",
8 | db : "chat_messages_service_database"
9 | }
10 | ]
11 | }
12 | );
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/security/model/AuthRequestModel.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.security.model;
2 |
3 | import lombok.Getter;
4 | import lombok.NoArgsConstructor;
5 |
6 | @Getter
7 | @NoArgsConstructor
8 | public class AuthRequestModel {
9 |
10 | private String username;
11 | private String password;
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/exception-utils/src/main/java/pl/kubaretip/exceptionutils/error/Violation.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.exceptionutils.error;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Getter;
5 |
6 | import java.util.List;
7 |
8 | @Getter
9 | @AllArgsConstructor
10 | public class Violation {
11 | private String field;
12 | private List message;
13 | }
14 |
--------------------------------------------------------------------------------
/auth-service/src/main/resources/db/migration/V1.0.3__create_user_authority_table.sql:
--------------------------------------------------------------------------------
1 | create table if not exists user_authority
2 | (
3 | user_id binary(16) not null,
4 | authority_name varchar(50) not null,
5 | primary key (user_id, authority_name),
6 | foreign key (user_id) references user (id),
7 | foreign key (authority_name) references authority (name)
8 | );
--------------------------------------------------------------------------------
/config-server/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | encrypt:
2 | key: ${CONFIG_SERVER_SECRET}
3 | spring:
4 | cloud:
5 | config:
6 | server:
7 | git:
8 | uri: ${GIT_URI}
9 | search-paths:
10 | - 'files'
11 | - 'files/service/commons'
12 | - 'files/service/*-service'
13 | default-label: ${GIT_BRANCH}
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/exception/handler/CustomExceptionsHandler.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.exception.handler;
2 |
3 | import org.springframework.web.bind.annotation.RestControllerAdvice;
4 | import pl.kubaretip.exceptionutils.CommonExceptionHandler;
5 |
6 | @RestControllerAdvice
7 | public class CustomExceptionsHandler implements CommonExceptionHandler {
8 | }
9 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/exception/controllerAdvice/CustomExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.exception.controllerAdvice;
2 |
3 | import org.springframework.web.bind.annotation.RestControllerAdvice;
4 | import pl.kubaretip.exceptionutils.CommonExceptionHandler;
5 |
6 | @RestControllerAdvice
7 | public class CustomExceptionHandler implements CommonExceptionHandler {
8 | }
9 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/dto/FriendChatDTO.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.dto;
2 |
3 | import lombok.Getter;
4 | import lombok.NoArgsConstructor;
5 | import lombok.Setter;
6 |
7 | @Setter
8 | @Getter
9 | @NoArgsConstructor
10 | public class FriendChatDTO {
11 |
12 | private Long id;
13 | private Long chatWith;
14 | private ChatProfileDTO recipient;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/exception/InvalidAuthenticationRequestException.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.exception;
2 |
3 | import org.springframework.security.core.AuthenticationException;
4 |
5 | public class InvalidAuthenticationRequestException extends AuthenticationException {
6 | public InvalidAuthenticationRequestException(String msg) {
7 | super(msg);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/constants/ApplicationConstants.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.constants;
2 |
3 | public final class ApplicationConstants {
4 |
5 | public final static int USER_PASSWORD_MIN_LENGTH = 6;
6 | public final static int USER_PASSWORD_MAX_LENGTH = 32;
7 | public final static String LOGIN_REGEXP = "^[a-zA-Z0-9]*$";
8 |
9 |
10 | private ApplicationConstants() {
11 | }
12 | }
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/service/ChatProfileService.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.service;
2 |
3 | import pl.kubaretip.chatservice.domain.ChatProfile;
4 |
5 | public interface ChatProfileService {
6 | ChatProfile createChatProfile(String userId, String username);
7 |
8 | ChatProfile generateNewFriendsRequestCode(String userId, String username);
9 |
10 | ChatProfile getChatProfileById(String userId);
11 | }
12 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/repository/AuthorityRepository.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.repository;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 | import pl.kubaretip.authservice.domain.Authority;
5 |
6 | import java.util.Optional;
7 |
8 | public interface AuthorityRepository extends JpaRepository {
9 |
10 | Optional findByNameIgnoreCase(String name);
11 |
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/cloud-gateway/src/main/resources/bootstrap-docker.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | uri: ${CLOUD_CONFIG_URI}
5 | fail-fast: true
6 | retry:
7 | max-attempts: 20
8 | initial-interval: 15000
9 | max-interval: 10000
10 | management:
11 | endpoint:
12 | restart:
13 | enabled: true
14 | endpoints:
15 | web:
16 | exposure:
17 | include:
18 | - health
19 | - info
20 | - restart
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/security/model/TokenResponse.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.security.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Getter;
6 | import lombok.NoArgsConstructor;
7 |
8 | @Getter
9 | @NoArgsConstructor
10 | @AllArgsConstructor
11 | public class TokenResponse {
12 |
13 | @JsonProperty("access_token")
14 | private String accessToken;
15 |
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/dto/ChatProfileDTO.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.dto;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import lombok.Getter;
5 | import lombok.NoArgsConstructor;
6 | import lombok.Setter;
7 |
8 | @JsonInclude(JsonInclude.Include.NON_NULL)
9 | @Getter
10 | @Setter
11 | @NoArgsConstructor
12 | public class ChatProfileDTO {
13 |
14 | private String userId;
15 | private String friendsRequestCode;
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/auth-service/src/main/resources/db/migration/V1.0.2__create_user_table.sql:
--------------------------------------------------------------------------------
1 | create table if not exists user
2 | (
3 | id binary(16) not null primary key,
4 | username varchar(50) not null unique,
5 | password_hash varchar(60) not null,
6 | first_name varchar(50) not null,
7 | last_name varchar(50) not null,
8 | activation_key varchar(124) unique,
9 | email varchar(100) not null unique,
10 | enabled boolean not null default 0
11 | );
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/repository/ChatProfileRepository.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.repository;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 | import pl.kubaretip.chatservice.domain.ChatProfile;
5 |
6 | import java.util.Optional;
7 | import java.util.UUID;
8 |
9 | public interface ChatProfileRepository extends JpaRepository {
10 |
11 | Optional findByFriendsRequestCode(String friendsRequestCode);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/docker/.env.dev:
--------------------------------------------------------------------------------
1 | # you can change this starting passwords but you must recrypt all in config repo
2 | AUTH_SERVICE_MYSQL_USER=auth-service-user
3 | AUTH_SERVICE_MYSQL_PASS=auth-service-pass-123
4 | AUTH_SERVICE_MYSQL_ROOT_PASS=auth-service-root-pass-123
5 | CHAT_SERVICE_MYSQL_USER=chat-service-user
6 | CHAT_SERVICE_MYSQL_PASS=chat-service-pass-123
7 | CHAT_SERVICE_MYSQL_ROOT_PASS=chat-service-root-pass-123
8 | CHAT_MESSAGES_SERVICE_ROOT_MONGO_USER=chat-messages-service-root
9 | CHAT_MESSAGES_SERVICE_ROOT_MONGO_PASS=chat-messages-service-root-pass-123
--------------------------------------------------------------------------------
/config-server/src/main/resources/bootstrap-docker.yml:
--------------------------------------------------------------------------------
1 | encrypt:
2 | key: ${CONFIG_SERVER_SECRET}
3 |
4 | spring:
5 | cloud:
6 | config:
7 | server:
8 | git:
9 | uri: ${GIT_URI}
10 | search-paths:
11 | - 'files'
12 | - 'files/service/commons'
13 | - 'files/service/*-service'
14 | default-label: ${GIT_BRANCH}
15 | ignore-local-ssh-settings: true
16 | host-key-algorithm: ssh-rsa
17 | host-key: ${HOST_KEY}
18 | private-key: ${PRIVATE_KEY}
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/AuthServiceApplication.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
6 |
7 | @EnableEurekaClient
8 | @SpringBootApplication
9 | public class AuthServiceApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(AuthServiceApplication.class, args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/dto/FriendRequestDTO.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.dto;
2 |
3 |
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 | import lombok.Getter;
6 | import lombok.NoArgsConstructor;
7 | import lombok.Setter;
8 |
9 | @JsonInclude(JsonInclude.Include.NON_NULL)
10 | @Getter
11 | @Setter
12 | @NoArgsConstructor
13 | public class FriendRequestDTO {
14 |
15 | private Long id;
16 | private String sentTime;
17 | private ChatProfileDTO sender;
18 | private ChatProfileDTO recipient;
19 | }
20 |
--------------------------------------------------------------------------------
/eureka-server/src/main/java/pl/kubaretip/eurekaserver/EurekaServerApplication.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.eurekaserver;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
6 |
7 | @EnableEurekaServer
8 | @SpringBootApplication
9 | public class EurekaServerApplication {
10 | public static void main(String[] args) {
11 | SpringApplication.run(EurekaServerApplication.class, args);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/mail-service/src/main/java/pl/kubaretip/mailservice/MailServiceApplication.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.mailservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
6 |
7 | @EnableEurekaClient
8 | @SpringBootApplication
9 | public class MailServiceApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(MailServiceApplication.class, args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/chat-service/src/main/resources/db/migration/V1.0.3__create_friend_chat_table.sql:
--------------------------------------------------------------------------------
1 | create table if not exists friend_chat
2 | (
3 | id bigint not null primary key auto_increment,
4 | chat_with_id bigint,
5 | sender_id binary(16) not null,
6 | recipient_id binary(16) not null,
7 | foreign key (chat_with_id) references friend_chat (id),
8 | foreign key (sender_id) references chat_profile (user_id),
9 | foreign key (recipient_id) references chat_profile (user_id),
10 | unique index (chat_with_id, sender_id, recipient_id)
11 | );
--------------------------------------------------------------------------------
/cloud-gateway/src/main/java/pl/kubaretip/cloudgateway/CloudGatewayApplication.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.cloudgateway;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
6 |
7 | @EnableEurekaClient
8 | @SpringBootApplication
9 | public class CloudGatewayApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(CloudGatewayApplication.class, args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/config-server/src/main/java/pl/kubaretip/configserver/ConfigServerApplication.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.configserver;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.config.server.EnableConfigServer;
6 |
7 | @EnableConfigServer
8 | @SpringBootApplication
9 | public class ConfigServerApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(ConfigServerApplication.class, args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
35 | docker/.env
36 | .env
--------------------------------------------------------------------------------
/docker/rabbitmq-isolated.conf:
--------------------------------------------------------------------------------
1 | [
2 | {rabbit,
3 | [
4 | %% The default "guest" user is only permitted to access the server
5 | %% via a loopback interface (e.g. localhost).
6 | {loopback_users, [<<"rabbitmq-user">>]},
7 | %%
8 | %% Uncomment the following line if you want to allow access to the
9 | %% guest user from anywhere on the network.
10 | {loopback_users, []},
11 | {default_vhost, "/"},
12 | {default_user, "rabbitmq-user"},
13 | {default_pass, "rabbitmq-pass-123"},
14 | {default_permissions, [".*", ".*", ".*"]}
15 | ]}
16 | ].
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/service/FriendChatService.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.service;
2 |
3 | import pl.kubaretip.chatservice.domain.ChatProfile;
4 | import pl.kubaretip.chatservice.domain.FriendChat;
5 |
6 | import java.util.List;
7 |
8 | public interface FriendChatService {
9 | void createFriendChat(ChatProfile firstUserChatProfile, ChatProfile secondUserChatProfile);
10 |
11 | List getAllFriendsChatsBySender(String currentUser);
12 |
13 | void deleteFriendChat(long friendChatId, long friendChatWithId, String currentUserId);
14 | }
15 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/service/UserService.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.service;
2 |
3 | import pl.kubaretip.authservice.domain.User;
4 |
5 | public interface UserService {
6 | User createUser(String username, String password, String email, String firstName, String lastName);
7 |
8 | void activateUser(String activationKey);
9 |
10 | User findUserById(String userId);
11 |
12 | User modifyUser(String userId, String firstName, String lastName);
13 |
14 | void changeUserPassword(String userId, String currentPassword, String newPassword);
15 | }
16 |
--------------------------------------------------------------------------------
/chat-messages-service/src/main/java/pl/kubaretip/chatmessagesservice/ChatMessagesServiceApplication.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatmessagesservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
6 |
7 | @EnableEurekaClient
8 | @SpringBootApplication
9 | public class ChatMessagesServiceApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(ChatMessagesServiceApplication.class, args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/dto-models/src/main/java/pl/kubaretip/dtomodels/ChatMessageDTO.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.dtomodels;
2 |
3 |
4 | import lombok.Getter;
5 | import lombok.NoArgsConstructor;
6 | import lombok.Setter;
7 | import lombok.ToString;
8 |
9 | import java.io.Serializable;
10 |
11 | @ToString
12 | @Getter
13 | @Setter
14 | @NoArgsConstructor
15 | public class ChatMessageDTO implements Serializable {
16 |
17 | private String id;
18 | private Long friendChat;
19 | private String sender;
20 | private String recipient;
21 | private String content;
22 | private String time;
23 | private String status;
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/exception-utils/src/main/java/pl/kubaretip/exceptionutils/error/Error.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.exceptionutils.error;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import lombok.Builder;
5 | import lombok.Getter;
6 |
7 | import java.util.Date;
8 | import java.util.Set;
9 |
10 | @JsonInclude(JsonInclude.Include.NON_NULL)
11 | @Builder
12 | @Getter
13 | public class Error {
14 |
15 | @Builder.Default
16 | private final Date timestamp = new Date();
17 | private int status;
18 | private String title;
19 | private String detail;
20 | private String path;
21 | private Set violations;
22 | }
23 |
--------------------------------------------------------------------------------
/chat-service/src/main/resources/db/migration/V1.0.2__create_friend_request_table.sql:
--------------------------------------------------------------------------------
1 | create table if not exists friend_request
2 | (
3 | id bigint not null auto_increment primary key,
4 | sender_chat_profile_id binary(16) not null,
5 | recipient_chat_profile_id binary(16) not null,
6 | sent_time datetime(6) not null,
7 | is_accepted boolean not null default 0,
8 | foreign key (sender_chat_profile_id) references chat_profile (user_id),
9 | foreign key (recipient_chat_profile_id) references chat_profile (user_id),
10 | unique index (sender_chat_profile_id, recipient_chat_profile_id)
11 | )
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.repository;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 | import pl.kubaretip.authservice.domain.User;
5 |
6 |
7 | import java.util.Optional;
8 | import java.util.UUID;
9 |
10 | public interface UserRepository extends JpaRepository {
11 |
12 | Optional findOneWithAuthoritiesByUsernameIgnoreCase(String username);
13 |
14 | boolean existsByUsernameIgnoreCase(String username);
15 |
16 | boolean existsByEmailIgnoreCase(String email);
17 |
18 | Optional findOneByActivationKey(String activationKey);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/chat-messages-service/src/main/java/pl/kubaretip/chatmessagesservice/security/SecurityUtils.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatmessagesservice.security;
2 |
3 | import org.springframework.security.core.context.ReactiveSecurityContextHolder;
4 | import pl.kubaretip.authutils.security.SecurityUserDetails;
5 | import reactor.core.publisher.Mono;
6 |
7 | public class SecurityUtils {
8 |
9 | public static Mono getCurrentUser() {
10 | return ReactiveSecurityContextHolder.getContext()
11 | .map(context -> context.getAuthentication().getPrincipal())
12 | .cast(SecurityUserDetails.class)
13 | .map(SecurityUserDetails::getId);
14 | }
15 |
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/auth-utils/src/main/java/pl/kubaretip/authutils/jwt/JWTConfig.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authutils.jwt;
2 |
3 | import lombok.Getter;
4 | import org.springframework.beans.factory.annotation.Value;
5 |
6 | @Getter
7 | public class JWTConfig {
8 |
9 | @Value("${security.jwt.uri:/authenticate}")
10 | private String authEndpoint;
11 |
12 | @Value("${security.jwt.header:Authorization}")
13 | private String header;
14 |
15 | @Value("${security.jwt.prefix:Bearer }")
16 | private String tokenPrefix;
17 |
18 | @Value("${security.jwt.expiration:#{24*60*60}}")
19 | private int expiration;
20 |
21 | @Value("${security.jwt.secret:jwtSecretKey123}")
22 | private String secret;
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/util/DateUtils.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.util;
2 |
3 | import java.time.LocalDateTime;
4 | import java.time.OffsetDateTime;
5 | import java.time.format.DateTimeFormatter;
6 | import java.util.TimeZone;
7 |
8 | public final class DateUtils {
9 |
10 | public static final String DATE_PATTERN = "dd.MM.yyyy HH:mm:ss";
11 |
12 | public static OffsetDateTime convertStringDateToOffsetTime(String time) {
13 | var localDateTime = LocalDateTime.parse(time, DateTimeFormatter.ofPattern(DATE_PATTERN));
14 | var zoneOffset = TimeZone.getDefault().toZoneId().getRules().getOffset(localDateTime);
15 | return localDateTime.atOffset(zoneOffset);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/domain/ChatProfile.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.domain;
2 |
3 | import lombok.Getter;
4 | import lombok.NoArgsConstructor;
5 | import lombok.Setter;
6 |
7 | import javax.persistence.*;
8 | import java.util.UUID;
9 |
10 |
11 | @Getter
12 | @Setter
13 | @Table(name = "chat_profile", schema = "chat_service_database")
14 | @Entity
15 | @NoArgsConstructor
16 | public class ChatProfile {
17 |
18 | @Id
19 | @Column(nullable = false, name = "user_id", unique = true, columnDefinition = "BINARY(16)")
20 | private UUID userId;
21 |
22 | @Column(name = "friends_request_code", nullable = false, length = 64, unique = true)
23 | private String friendsRequestCode;
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/service/FriendRequestService.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.service;
2 |
3 | import pl.kubaretip.chatservice.domain.FriendRequest;
4 |
5 | import java.util.List;
6 |
7 | public interface FriendRequestService {
8 | FriendRequest createNewFriendRequest(String currentUserId, String friendRequestCode);
9 |
10 | void replyToFriendRequest(long friendRequestId, String currentUserId, boolean accept);
11 |
12 | void deleteFriendRequestBySender(String senderId, long friendRequestId);
13 |
14 | List getAllNotAcceptedFriendRequestsByRecipientId(String recipientId);
15 |
16 | List getAllNotAcceptedFriendRequestsBySenderId(String senderId);
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/auth-utils/src/main/java/pl/kubaretip/authutils/SecurityUtils.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authutils;
2 |
3 | import org.springframework.security.core.context.SecurityContextHolder;
4 | import pl.kubaretip.authutils.security.SecurityUserDetails;
5 |
6 | public class SecurityUtils {
7 |
8 | public static String getCurrentUser() {
9 | var principal = (SecurityUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
10 | return principal.getId();
11 | }
12 |
13 | public static String getCurrentUserPreferredUsername(){
14 | var principal = (SecurityUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
15 | return principal.getUsername();
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/auth-service/src/test/java/pl/kubaretip/authservice/utils/JacksonIgnoreWriteOnlyAccess.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.utils;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import com.fasterxml.jackson.databind.introspect.Annotated;
5 | import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
6 |
7 | public class JacksonIgnoreWriteOnlyAccess extends JacksonAnnotationIntrospector {
8 |
9 |
10 | @Override
11 | public JsonProperty.Access findPropertyAccess(Annotated m) {
12 | JsonProperty.Access access = super.findPropertyAccess(m);
13 | if (access == JsonProperty.Access.WRITE_ONLY) {
14 | return JsonProperty.Access.AUTO;
15 | }
16 | return access;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/dto/mapper/ChatProfileMapper.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.dto.mapper;
2 |
3 | import org.mapstruct.Mapper;
4 | import org.mapstruct.Mapping;
5 | import org.mapstruct.Named;
6 | import pl.kubaretip.chatservice.domain.ChatProfile;
7 | import pl.kubaretip.chatservice.dto.ChatProfileDTO;
8 |
9 | import java.util.UUID;
10 |
11 | @Mapper(componentModel = "spring")
12 | public interface ChatProfileMapper {
13 |
14 | @Named("chatProfileToChatProfileDTO")
15 | @Mapping(target = "userId", expression = "java(convertUUIDtoString(chatProfile.getUserId()))")
16 | ChatProfileDTO chatProfileToChatProfileDTO(ChatProfile chatProfile);
17 |
18 | default String convertUUIDtoString(UUID id) {
19 | return id.toString();
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/ChatServiceApplication.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
6 | import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
7 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
8 |
9 | @EnableEurekaClient
10 | @SpringBootApplication(exclude = {SecurityAutoConfiguration.class, UserDetailsServiceAutoConfiguration.class})
11 | public class ChatServiceApplication {
12 | public static void main(String[] args) {
13 | SpringApplication.run(ChatServiceApplication.class, args);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/config/RabbitMQConfig.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.config;
2 |
3 | import org.springframework.amqp.core.FanoutExchange;
4 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import pl.kubaretip.authservice.messaging.sender.UserSender;
8 |
9 | @Configuration
10 | public class RabbitMQConfig {
11 |
12 | @Bean
13 | public FanoutExchange fanoutExchange() {
14 | return new FanoutExchange("pl.kubaretip.authservice.fanout");
15 | }
16 |
17 |
18 | @Bean
19 | public UserSender userSender(RabbitTemplate rabbitTemplate, FanoutExchange fanoutExchange) {
20 | return new UserSender(rabbitTemplate, fanoutExchange);
21 | }
22 |
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/domain/Authority.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.domain;
2 |
3 | import lombok.Getter;
4 | import lombok.NoArgsConstructor;
5 | import lombok.Setter;
6 | import lombok.ToString;
7 | import org.hibernate.annotations.Immutable;
8 |
9 | import javax.persistence.Column;
10 | import javax.persistence.Entity;
11 | import javax.persistence.Id;
12 | import javax.persistence.Table;
13 | import java.io.Serializable;
14 |
15 | @ToString
16 | @Entity
17 | @Table(schema = "auth_service_database")
18 | @Getter
19 | @Setter
20 | @NoArgsConstructor
21 | @Immutable
22 | public class Authority implements Serializable {
23 |
24 | public static final long serialVersionUID = -8053205789790776096L;
25 |
26 | @Id
27 | @Column(length = 50, nullable = false, unique = true)
28 | private String name;
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/mail-service/src/main/java/pl/kubaretip/mailservice/messaging/listener/RabbitUserActivationListener.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.mailservice.messaging.listener;
2 |
3 |
4 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
5 | import org.springframework.stereotype.Component;
6 | import pl.kubaretip.dtomodels.UserDTO;
7 | import pl.kubaretip.mailservice.service.SendMailService;
8 |
9 | @Component
10 | public class RabbitUserActivationListener {
11 |
12 | private final SendMailService sendMailService;
13 |
14 | public RabbitUserActivationListener(SendMailService sendMailService) {
15 | this.sendMailService = sendMailService;
16 |
17 | }
18 |
19 | @RabbitListener(queues = "#{usersActivationQueue.name}")
20 | public void receiveNewUser(UserDTO userDTO) {
21 | sendMailService.sendActivationEmail(userDTO);
22 | }
23 |
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/messages-websocket-service/src/main/java/pl/kubaretip/messageswebsocketservice/log/WebSocketLogs.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.messageswebsocketservice.log;
2 |
3 | import org.springframework.context.annotation.Profile;
4 | import org.springframework.stereotype.Component;
5 | import org.springframework.web.socket.config.WebSocketMessageBrokerStats;
6 |
7 | import javax.annotation.PostConstruct;
8 |
9 | @Profile("dev")
10 | @Component
11 | public class WebSocketLogs {
12 |
13 | private final WebSocketMessageBrokerStats webSocketMessageBrokerStats;
14 |
15 | public WebSocketLogs(WebSocketMessageBrokerStats webSocketMessageBrokerStats) {
16 | this.webSocketMessageBrokerStats = webSocketMessageBrokerStats;
17 | }
18 |
19 | @PostConstruct
20 | public void init() {
21 | webSocketMessageBrokerStats.setLoggingPeriod(30 * 1000);
22 | }
23 |
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/web/model/ChangePassRequest.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.web.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Getter;
5 | import lombok.NoArgsConstructor;
6 | import lombok.Setter;
7 | import pl.kubaretip.authservice.constants.ApplicationConstants;
8 |
9 | import javax.validation.constraints.NotBlank;
10 | import javax.validation.constraints.Size;
11 |
12 | @AllArgsConstructor
13 | @NoArgsConstructor
14 | @Getter
15 | @Setter
16 | public class ChangePassRequest {
17 |
18 | @NotBlank
19 | @Size(min = ApplicationConstants.USER_PASSWORD_MIN_LENGTH, max = ApplicationConstants.USER_PASSWORD_MAX_LENGTH)
20 | private String currentPassword;
21 |
22 | @NotBlank
23 | @Size(min = ApplicationConstants.USER_PASSWORD_MIN_LENGTH, max = ApplicationConstants.USER_PASSWORD_MAX_LENGTH)
24 | private String newPassword;
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/messages-websocket-service/src/main/java/pl/kubaretip/messageswebsocketservice/MessagesWebSocketServiceApplication.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.messageswebsocketservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
6 | import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
7 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
8 |
9 | @EnableEurekaClient
10 | @SpringBootApplication(exclude = {SecurityAutoConfiguration.class, UserDetailsServiceAutoConfiguration.class})
11 | public class MessagesWebSocketServiceApplication {
12 |
13 | public static void main(String[] args) {
14 | SpringApplication.run(MessagesWebSocketServiceApplication.class, args);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/chat-messages-service/src/main/java/pl/kubaretip/chatmessagesservice/document/ChatMessage.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatmessagesservice.document;
2 |
3 | import lombok.Getter;
4 | import lombok.NoArgsConstructor;
5 | import lombok.Setter;
6 | import org.springframework.data.annotation.Id;
7 | import org.springframework.data.mongodb.core.mapping.Document;
8 | import org.springframework.data.mongodb.core.mapping.Field;
9 | import pl.kubaretip.chatmessagesservice.constant.MessageStatus;
10 |
11 | import java.util.Date;
12 |
13 | @Getter
14 | @Setter
15 | @NoArgsConstructor
16 | @Document(collection = "chat_message")
17 | public class ChatMessage {
18 |
19 | @Id
20 | private String id;
21 |
22 | @Field(name = "friend_chat")
23 | private Long friendChat;
24 | private String sender;
25 | private String recipient;
26 | private String content;
27 | private Date time;
28 | private MessageStatus status;
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/chat-messages-service/src/main/java/pl/kubaretip/chatmessagesservice/messaging/listener/RabbitMessageDeletingListener.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatmessagesservice.messaging.listener;
2 |
3 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
4 | import org.springframework.stereotype.Component;
5 | import pl.kubaretip.chatmessagesservice.service.ChatMessageService;
6 |
7 | import java.util.List;
8 |
9 | @Component
10 | public class RabbitMessageDeletingListener {
11 |
12 | private final ChatMessageService chatMessageService;
13 |
14 | public RabbitMessageDeletingListener(ChatMessageService chatMessageService) {
15 | this.chatMessageService = chatMessageService;
16 | }
17 |
18 | @RabbitListener(queues = "#{messageDeletingQueue.name}")
19 | public void receiveNewChatMessage(List friendChatIds) {
20 | chatMessageService.removeMessagesByFriendChat(friendChatIds).subscribe();
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/messages-websocket-service/src/main/java/pl/kubaretip/messageswebsocketservice/config/RabbitMQConfig.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.messageswebsocketservice.config;
2 |
3 | import org.springframework.amqp.core.FanoutExchange;
4 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import pl.kubaretip.messageswebsocketservice.messaging.sender.StoringMessagesSender;
8 |
9 | @Configuration
10 | public class RabbitMQConfig {
11 |
12 | @Bean
13 | public FanoutExchange fanoutExchange() {
14 | return new FanoutExchange("pl.kubaretip.chatmessagesservice.fanout");
15 | }
16 |
17 | @Bean
18 | public StoringMessagesSender storingMessagesSender(RabbitTemplate rabbitTemplate, FanoutExchange fanoutExchange) {
19 | return new StoringMessagesSender(rabbitTemplate, fanoutExchange);
20 | }
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/messages-websocket-service/src/main/java/pl/kubaretip/messageswebsocketservice/config/WebSocketSecurityConfig.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.messageswebsocketservice.config;
2 |
3 | import org.springframework.context.annotation.Configuration;
4 | import org.springframework.security.config.annotation.web.messaging.MessageSecurityMetadataSourceRegistry;
5 | import org.springframework.security.config.annotation.web.socket.AbstractSecurityWebSocketMessageBrokerConfigurer;
6 |
7 | @Configuration
8 | public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
9 |
10 | @Override
11 | protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
12 | messages.anyMessage().authenticated();
13 | }
14 |
15 | // TODO: Temporarily disabled CRSF.
16 | // In the future provide CRSF endpoint.
17 | @Override
18 | protected boolean sameOriginDisabled() {
19 | return true;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/mapper/UserMapper.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.mapper;
2 |
3 | import org.mapstruct.InheritConfiguration;
4 | import org.mapstruct.Mapper;
5 | import org.mapstruct.Mapping;
6 | import pl.kubaretip.authservice.domain.User;
7 | import pl.kubaretip.dtomodels.UserDTO;
8 |
9 | import java.util.UUID;
10 |
11 | @Mapper(componentModel = "spring")
12 | public interface UserMapper {
13 |
14 | @Mapping(target = "password", ignore = true)
15 | @Mapping(target = "id", expression = "java(convertIdToString(user.getId()))")
16 | UserDTO mapToUserDTO(User user);
17 |
18 | @InheritConfiguration(name = "mapToUserDTO")
19 | @Mapping(target = "activationKey", ignore = true)
20 | UserDTO mapToUserDTOWithoutActivationKey(User user);
21 |
22 | default String convertIdToString(UUID id) {
23 | if (id == null) {
24 | return null;
25 | }
26 | return id.toString();
27 | }
28 |
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/messaging/sender/UserSender.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.messaging.sender;
2 |
3 | import org.springframework.amqp.core.FanoutExchange;
4 | import org.springframework.amqp.core.MessageProperties;
5 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
6 | import pl.kubaretip.dtomodels.UserDTO;
7 |
8 |
9 | public class UserSender {
10 |
11 | private final RabbitTemplate template;
12 | private final FanoutExchange fanout;
13 |
14 | public UserSender(RabbitTemplate template, FanoutExchange fanout) {
15 | this.template = template;
16 | this.fanout = fanout;
17 | }
18 |
19 |
20 | public void send(UserDTO userDTO) {
21 | var converter = template.getMessageConverter();
22 | var messageProperties = new MessageProperties();
23 | var message = converter.toMessage(userDTO, messageProperties);
24 | template.send(fanout.getName(), "", message);
25 | }
26 |
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/messaging/listener/RabbitNewUserListener.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.messaging.listener;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
5 | import org.springframework.stereotype.Component;
6 | import pl.kubaretip.chatservice.service.ChatProfileService;
7 | import pl.kubaretip.dtomodels.UserDTO;
8 |
9 | @Slf4j
10 | @Component
11 | public class RabbitNewUserListener {
12 |
13 | private final ChatProfileService chatProfileService;
14 |
15 | public RabbitNewUserListener(ChatProfileService chatProfileService) {
16 | this.chatProfileService = chatProfileService;
17 | }
18 |
19 |
20 | @RabbitListener(queues = "#{newUsersQueue.name}")
21 | public void receiveNewUser(UserDTO userDTO) {
22 | log.debug("New user {}", userDTO.getUsername());
23 | chatProfileService.createChatProfile(userDTO.getId(), userDTO.getUsername());
24 | }
25 |
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/messaging/sender/DeleteMessagesSender.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.messaging.sender;
2 |
3 | import org.springframework.amqp.core.FanoutExchange;
4 | import org.springframework.amqp.core.MessageProperties;
5 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
6 |
7 | import java.util.List;
8 |
9 | public class DeleteMessagesSender {
10 |
11 | private final RabbitTemplate template;
12 | private final FanoutExchange fanout;
13 |
14 | public DeleteMessagesSender(RabbitTemplate template, FanoutExchange fanout) {
15 | this.template = template;
16 | this.fanout = fanout;
17 | }
18 |
19 | public void sendDeletingMessagesTask(List friendChatIds) {
20 | var converter = template.getMessageConverter();
21 | var messageProperties = new MessageProperties();
22 | var message = converter.toMessage(friendChatIds, messageProperties);
23 | template.send(fanout.getName(), "", message);
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/chat-messages-service/src/main/java/pl/kubaretip/chatmessagesservice/service/ChatMessageService.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatmessagesservice.service;
2 |
3 | import pl.kubaretip.chatmessagesservice.document.ChatMessage;
4 | import reactor.core.publisher.Flux;
5 | import reactor.core.publisher.Mono;
6 |
7 | import java.util.List;
8 |
9 | public interface ChatMessageService {
10 |
11 | Flux findLastUsersMessagesFromTime(long firstUserFriendChatId, long secondUserFriendChatId,
12 | String beforeTime, int numberOfMessagesToFetch);
13 |
14 | Flux getLastUserMessages(long friendChatId1, long friendChatId2, int numberOfMessagesToFetch);
15 |
16 | Mono setDeliveredStatusForAllRecipientMessagesInFriendChat(long friendChatId, String currentUser);
17 |
18 | Mono saveChatMessage(Long friendChat, String sender, String recipient, String content, String time);
19 |
20 | Mono removeMessagesByFriendChat(List ids);
21 | }
22 |
--------------------------------------------------------------------------------
/docker/.env.docker:
--------------------------------------------------------------------------------
1 | # you can change this starting passwords but you must recrypt all in config repo
2 | AUTH_SERVICE_MYSQL_USER=auth-service-user
3 | AUTH_SERVICE_MYSQL_PASS=auth-service-pass-123
4 | AUTH_SERVICE_MYSQL_ROOT_PASS=auth-service-root-pass-123
5 | CHAT_SERVICE_MYSQL_USER=chat-service-user
6 | CHAT_SERVICE_MYSQL_PASS=chat-service-pass-123
7 | CHAT_SERVICE_MYSQL_ROOT_PASS=chat-service-root-pass-123
8 | CHAT_MESSAGES_SERVICE_ROOT_MONGO_USER=chat-messages-service-root
9 | CHAT_MESSAGES_SERVICE_ROOT_MONGO_PASS=chat-messages-service-root-pass-123
10 | # if you change config server secret you must recrypt all encypted password in config repo
11 | CONFIG_SERVER_SECRET=superSERCRET
12 | CONFIG_SERVER_URI=http://config-server:8888
13 | PROFILE=docker
14 | # repo with configuration files
15 | REPO_BRANCH=
16 | GIT_REPO_URI=
17 | # location .ssh/known_host key without ssh-rsa
18 | KNOWN_HOST_KEY=
19 | # generation ssh key ssh-keygen -m PEM -t rsa -b 4096
20 | PEM="|
21 | -----BEGIN RSA PRIVATE KEY-----
22 | ...
23 | -----END RSA PRIVATE KEY-----"
--------------------------------------------------------------------------------
/mail-service/src/main/java/pl/kubaretip/mailservice/config/RabbitMQConfig.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.mailservice.config;
2 |
3 | import org.springframework.amqp.core.Binding;
4 | import org.springframework.amqp.core.BindingBuilder;
5 | import org.springframework.amqp.core.FanoutExchange;
6 | import org.springframework.amqp.core.Queue;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 |
10 | @Configuration
11 | public class RabbitMQConfig {
12 |
13 | @Bean
14 | public FanoutExchange fanoutExchange() {
15 | return new FanoutExchange("pl.kubaretip.authservice.fanout");
16 | }
17 |
18 | @Bean
19 | public Queue usersActivationQueue() {
20 | return new Queue("pl.kubaretip.mailservice.activation");
21 | }
22 |
23 | @Bean
24 | public Binding bindingActivationMail(FanoutExchange fanoutExchange, Queue usersActivationQueue) {
25 | return BindingBuilder.bind(usersActivationQueue).to(fanoutExchange);
26 | }
27 |
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/messages-websocket-service/src/main/java/pl/kubaretip/messageswebsocketservice/messaging/sender/StoringMessagesSender.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.messageswebsocketservice.messaging.sender;
2 |
3 | import org.springframework.amqp.core.FanoutExchange;
4 | import org.springframework.amqp.core.MessageProperties;
5 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
6 | import pl.kubaretip.dtomodels.ChatMessageDTO;
7 |
8 | public class StoringMessagesSender {
9 |
10 | private final RabbitTemplate template;
11 | private final FanoutExchange fanout;
12 |
13 | public StoringMessagesSender(RabbitTemplate template, FanoutExchange fanout) {
14 | this.template = template;
15 | this.fanout = fanout;
16 | }
17 |
18 | public void send(ChatMessageDTO chatMessageDTO){
19 | var converter = template.getMessageConverter();
20 | var messageProperties = new MessageProperties();
21 | var message = converter.toMessage(chatMessageDTO, messageProperties);
22 | template.send(fanout.getName(), "", message);
23 | }
24 |
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/domain/FriendChat.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.domain;
2 |
3 |
4 | import lombok.Getter;
5 | import lombok.NoArgsConstructor;
6 | import lombok.Setter;
7 |
8 | import javax.persistence.*;
9 |
10 | @Getter
11 | @Setter
12 | @NoArgsConstructor
13 | @Table(schema = "chat_service_database", name = "friend_chat",
14 | uniqueConstraints = @UniqueConstraint(columnNames = {"chat_with_id", "sender_id", "recipient_id"}))
15 | @Entity
16 | public class FriendChat {
17 |
18 | @Id
19 | @GeneratedValue(strategy = GenerationType.IDENTITY)
20 | private Long id;
21 |
22 | @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.REMOVE})
23 | @JoinColumn(name = "chat_with_id")
24 | private FriendChat chatWith;
25 |
26 | @ManyToOne(fetch = FetchType.LAZY)
27 | @JoinColumn(name = "sender_id", nullable = false)
28 | private ChatProfile sender;
29 |
30 | @ManyToOne(fetch = FetchType.LAZY)
31 | @JoinColumn(name = "recipient_id", nullable = false)
32 | private ChatProfile recipient;
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/messages-websocket-service/src/main/java/pl/kubaretip/messageswebsocketservice/log/WebSocketConnectionListener.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.messageswebsocketservice.log;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.context.annotation.Profile;
5 | import org.springframework.context.event.EventListener;
6 | import org.springframework.stereotype.Component;
7 | import org.springframework.web.socket.messaging.SessionConnectEvent;
8 | import org.springframework.web.socket.messaging.SessionDisconnectEvent;
9 |
10 | import java.util.Date;
11 |
12 | @Profile("dev")
13 | @Slf4j
14 | @Component
15 | public class WebSocketConnectionListener {
16 |
17 |
18 | @EventListener(SessionConnectEvent.class)
19 | public void handleWebsocketConnectListener(SessionConnectEvent event) {
20 | log.debug("Session connected : {}", new Date().toString());
21 | }
22 |
23 | @EventListener(SessionDisconnectEvent.class)
24 | public void handleWebsocketDisconnectListener(SessionDisconnectEvent event) {
25 | log.debug("Session closed : {}", new Date().toString());
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/dto/mapper/FriendChatMapper.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.dto.mapper;
2 |
3 | import org.mapstruct.IterableMapping;
4 | import org.mapstruct.Mapper;
5 | import org.mapstruct.Mapping;
6 | import org.mapstruct.Named;
7 | import pl.kubaretip.chatservice.domain.FriendChat;
8 | import pl.kubaretip.chatservice.dto.FriendChatDTO;
9 |
10 | import java.util.List;
11 |
12 | @Mapper(componentModel = "spring", uses = ChatProfileMapper.class)
13 | public interface FriendChatMapper {
14 |
15 | @Named("mapToFriendChatWithIdChatWith")
16 | @Mapping(target = "chatWith", expression = "java(convertChatWithToId(friendChat.getChatWith()))")
17 | @Mapping(target = "recipient", qualifiedByName = "chatProfileToChatProfileDTO")
18 | FriendChatDTO mapToFriendChatDTO(FriendChat friendChat);
19 |
20 | @IterableMapping(qualifiedByName = {"mapToFriendChatWithIdChatWith"})
21 | List mapToFriendChatList(List friendChats);
22 |
23 | default Long convertChatWithToId(FriendChat chatWith) {
24 | return chatWith.getId();
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/chat-messages-service/src/main/java/pl/kubaretip/chatmessagesservice/repository/ChatMessageRepository.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatmessagesservice.repository;
2 |
3 | import org.springframework.data.domain.Pageable;
4 | import org.springframework.data.repository.reactive.ReactiveCrudRepository;
5 | import pl.kubaretip.chatmessagesservice.constant.MessageStatus;
6 | import pl.kubaretip.chatmessagesservice.document.ChatMessage;
7 | import reactor.core.publisher.Flux;
8 | import reactor.core.publisher.Mono;
9 |
10 | import java.util.Collection;
11 | import java.util.Date;
12 | import java.util.List;
13 |
14 |
15 | public interface ChatMessageRepository extends ReactiveCrudRepository {
16 |
17 | Flux findByTimeLessThanAndFriendChatIn(Date time, Collection ids, Pageable pageable);
18 |
19 | Flux findByFriendChatOrFriendChat(long firstUserChatId, long secondUserChatId, Pageable pageable);
20 |
21 | Flux findByFriendChatAndRecipientAndStatus(long friendChatId, String userId, MessageStatus status);
22 |
23 | Mono deleteByFriendChatIn(List ids);
24 | }
25 |
--------------------------------------------------------------------------------
/chat-messages-service/src/main/java/pl/kubaretip/chatmessagesservice/messaging/listener/RabbitMessageStoringListener.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatmessagesservice.messaging.listener;
2 |
3 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
4 | import org.springframework.stereotype.Component;
5 | import pl.kubaretip.chatmessagesservice.service.ChatMessageService;
6 | import pl.kubaretip.dtomodels.ChatMessageDTO;
7 |
8 | @Component
9 | public class RabbitMessageStoringListener {
10 |
11 | private final ChatMessageService chatMessageService;
12 |
13 | public RabbitMessageStoringListener(ChatMessageService chatMessageService) {
14 | this.chatMessageService = chatMessageService;
15 | }
16 |
17 | @RabbitListener(queues = "#{messageStoringQueue.name}")
18 | public void receiveNewChatMessage(ChatMessageDTO chatMessageDTO) {
19 | chatMessageService.saveChatMessage(chatMessageDTO.getFriendChat(),
20 | chatMessageDTO.getSender(),
21 | chatMessageDTO.getRecipient(),
22 | chatMessageDTO.getContent(),
23 | chatMessageDTO.getTime()).subscribe();
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/domain/FriendRequest.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.domain;
2 |
3 | import lombok.Getter;
4 | import lombok.NoArgsConstructor;
5 | import lombok.Setter;
6 |
7 | import javax.persistence.*;
8 | import java.time.OffsetDateTime;
9 |
10 |
11 | @Table(schema = "chat_service_database",
12 | name = "friend_request",
13 | uniqueConstraints = @UniqueConstraint(columnNames = {"sender_chat_profile_id", "recipient_chat_profile_id"}))
14 | @Entity
15 | @Getter
16 | @Setter
17 | @NoArgsConstructor
18 | public class FriendRequest {
19 |
20 | @Id
21 | @GeneratedValue(strategy = GenerationType.IDENTITY)
22 | private Long id;
23 |
24 | @Column(nullable = false, name = "sent_time")
25 | private OffsetDateTime sentTime;
26 |
27 | @ManyToOne(fetch = FetchType.LAZY)
28 | @JoinColumn(name = "sender_chat_profile_id", nullable = false)
29 | private ChatProfile sender;
30 |
31 | @ManyToOne(fetch = FetchType.LAZY)
32 | @JoinColumn(name = "recipient_chat_profile_id", nullable = false)
33 | private ChatProfile recipient;
34 |
35 | @Column(nullable = false, name = "is_accepted")
36 | private boolean isAccepted = false;
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/config-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spring-micro-websocket-chat
7 | pl.kubaretip
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | config-server
13 |
14 |
15 |
16 |
17 | org.springframework.boot
18 | spring-boot-starter-actuator
19 |
20 |
21 |
22 | org.springframework.cloud
23 | spring-cloud-config-server
24 |
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-test
29 | test
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/messages-websocket-service/src/main/java/pl/kubaretip/messageswebsocketservice/security/WebSocketAuthService.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.messageswebsocketservice.security;
2 |
3 | import com.auth0.jwt.exceptions.JWTDecodeException;
4 | import com.auth0.jwt.exceptions.TokenExpiredException;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
7 | import org.springframework.stereotype.Component;
8 | import pl.kubaretip.authutils.jwt.JWTUtils;
9 |
10 | @Slf4j
11 | @Component
12 | public class WebSocketAuthService {
13 |
14 | private final JWTUtils jwtUtils;
15 |
16 | public WebSocketAuthService(JWTUtils jwtUtils) {
17 | this.jwtUtils = jwtUtils;
18 | }
19 |
20 |
21 | public UsernamePasswordAuthenticationToken attemptAuthentication(String authorizationHeaderValue) {
22 |
23 | if (jwtUtils.isValidAuthorizationHeaderValue(authorizationHeaderValue)) {
24 | try {
25 | var token = authorizationHeaderValue.replace(jwtUtils.getJwtConfig().getTokenPrefix(), "");
26 | return jwtUtils.getAuthentication(token);
27 | } catch (JWTDecodeException | TokenExpiredException ex) {
28 | log.error("Invalid token");
29 | }
30 | }
31 | return null;
32 | }
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/auth-service/src/test/java/pl/kubaretip/authservice/mapper/UserMapperImplTest.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.mapper;
2 |
3 | import org.junit.jupiter.api.BeforeAll;
4 | import org.junit.jupiter.api.Test;
5 | import pl.kubaretip.authservice.domain.User;
6 |
7 | import static org.hamcrest.MatcherAssert.assertThat;
8 | import static org.hamcrest.Matchers.nullValue;
9 |
10 | public class UserMapperImplTest {
11 |
12 | private static UserMapperImpl userMapper;
13 |
14 | @BeforeAll
15 | public static void setup() {
16 | userMapper = new UserMapperImpl();
17 | }
18 |
19 | @Test
20 | public void shouldIgnorePasswordWhenMappingToDTO() {
21 |
22 | // given
23 | var user = new User();
24 | user.setPassword("passs");
25 |
26 | // when
27 | var userDTO = userMapper.mapToUserDTO(user);
28 |
29 | // then
30 | assertThat(userDTO.getPassword(), nullValue());
31 |
32 | }
33 |
34 | @Test
35 | public void shouldIgnoreActivationKeyWhenMappingToDTO() {
36 | // given
37 | var user = new User();
38 | user.setActivationKey("123");
39 |
40 | //when
41 | var userDTO = userMapper.mapToUserDTOWithoutActivationKey(user);
42 |
43 | //then
44 | assertThat(userDTO.getActivationKey(), nullValue());
45 | }
46 |
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/eureka-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spring-micro-websocket-chat
7 | pl.kubaretip
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | eureka-server
13 |
14 |
15 |
16 | org.springframework.cloud
17 | spring-cloud-starter-netflix-eureka-server
18 |
19 |
20 |
21 | org.springframework.cloud
22 | spring-cloud-starter-config
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-aop
28 |
29 |
30 |
31 | org.springframework.retry
32 | spring-retry
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/messages-websocket-service/src/main/java/pl/kubaretip/messageswebsocketservice/web/websocket/MessagesController.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.messageswebsocketservice.web.websocket;
2 |
3 | import org.springframework.messaging.handler.annotation.MessageMapping;
4 | import org.springframework.messaging.handler.annotation.Payload;
5 |
6 | import org.springframework.messaging.simp.SimpMessagingTemplate;
7 | import org.springframework.web.bind.annotation.RestController;
8 | import pl.kubaretip.dtomodels.ChatMessageDTO;
9 | import pl.kubaretip.messageswebsocketservice.messaging.sender.StoringMessagesSender;
10 |
11 |
12 | @RestController
13 | public class MessagesController {
14 |
15 | private final SimpMessagingTemplate simpMessagingTemplate;
16 | private final StoringMessagesSender storingMessagesSender;
17 |
18 | public MessagesController(SimpMessagingTemplate simpMessagingTemplate,
19 | StoringMessagesSender storingMessagesSender) {
20 | this.simpMessagingTemplate = simpMessagingTemplate;
21 | this.storingMessagesSender = storingMessagesSender;
22 | }
23 |
24 | @MessageMapping("/chat")
25 | public void processMessage(@Payload ChatMessageDTO chatMessage) {
26 | simpMessagingTemplate.convertAndSend("/topic/" + chatMessage.getRecipient() + ".messages", chatMessage);
27 | storingMessagesSender.send(chatMessage);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/mail-service/src/main/java/pl/kubaretip/mailservice/config/AsyncConfig.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.mailservice.config;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.boot.autoconfigure.task.TaskExecutionProperties;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.scheduling.annotation.EnableAsync;
8 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
9 |
10 | import java.util.concurrent.Executor;
11 |
12 | @Slf4j
13 | @Configuration
14 | @EnableAsync
15 | public class AsyncConfig {
16 |
17 | private final TaskExecutionProperties taskExecutionProperties;
18 |
19 | public AsyncConfig(TaskExecutionProperties taskExecutionProperties) {
20 | this.taskExecutionProperties = taskExecutionProperties;
21 | }
22 |
23 | @Bean
24 | public Executor taskExecutor() {
25 | var executor = new ThreadPoolTaskExecutor();
26 | executor.setCorePoolSize(taskExecutionProperties.getPool().getCoreSize());
27 | executor.setMaxPoolSize(taskExecutionProperties.getPool().getMaxSize());
28 | executor.setQueueCapacity(taskExecutionProperties.getPool().getQueueCapacity());
29 | executor.setThreadNamePrefix(taskExecutionProperties.getThreadNamePrefix());
30 | executor.initialize();
31 | return executor;
32 | }
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/repository/FriendChatRepository.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.repository;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 | import org.springframework.data.jpa.repository.Query;
5 | import pl.kubaretip.chatservice.domain.ChatProfile;
6 | import pl.kubaretip.chatservice.domain.FriendChat;
7 |
8 | import java.util.List;
9 | import java.util.Optional;
10 | import java.util.UUID;
11 |
12 | public interface FriendChatRepository extends JpaRepository {
13 |
14 |
15 | @Query("SELECT " +
16 | "CASE WHEN COUNT (fc) > 0 THEN true ELSE false END " +
17 | "FROM FriendChat fc WHERE (fc.sender = :chatProfile1 AND fc.recipient = :chatProfile2) " +
18 | "OR (fc.sender = :chatProfile2 AND fc.recipient = :chatProfile1)")
19 | boolean existsFriendChatForUsers(ChatProfile chatProfile1, ChatProfile chatProfile2);
20 |
21 |
22 | List findBySender(ChatProfile sender);
23 |
24 |
25 | @Query("SELECT fc from FriendChat fc WHERE fc.id = :friendChatId " +
26 | "AND fc.chatWith.id = :friendChatWithId " +
27 | "AND fc.sender.userId = :senderId")
28 | Optional findByIdAndFriendChatWithIdAndSenderId(long friendChatId,
29 | long friendChatWithId,
30 | UUID senderId);
31 |
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/cloud-gateway/src/main/java/pl/kubaretip/cloudgateway/config/OpenAPIConfig.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.cloudgateway.config;
2 |
3 | import org.springdoc.core.GroupedOpenApi;
4 | import org.springdoc.core.SwaggerUiConfigParameters;
5 | import org.springframework.cloud.gateway.route.RouteLocator;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 | import org.springframework.context.annotation.Lazy;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | @Configuration
14 | public class OpenAPIConfig {
15 |
16 | private RouteLocator locator;
17 |
18 | public OpenAPIConfig(RouteLocator locator) {
19 | this.locator = locator;
20 | }
21 |
22 | @Bean
23 | @Lazy(false)
24 | public List apis(SwaggerUiConfigParameters swaggerUiConfigParameters) {
25 | List groups = new ArrayList<>();
26 | locator.getRoutes()
27 | .subscribe(route -> {
28 | if (route.getId().toLowerCase().startsWith("ReactiveCompositeDiscoveryClient_".toLowerCase())) {
29 | String name = route.getId().replaceAll("ReactiveCompositeDiscoveryClient_", "");
30 | swaggerUiConfigParameters.addGroup(name);
31 | groups.add(GroupedOpenApi.builder().pathsToMatch("/" + name + "/v3/api-docs").group(name).build());
32 | }
33 | });
34 | return groups;
35 |
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/config/RabbitMQConfig.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.config;
2 |
3 | import org.springframework.amqp.core.Binding;
4 | import org.springframework.amqp.core.BindingBuilder;
5 | import org.springframework.amqp.core.FanoutExchange;
6 | import org.springframework.amqp.core.Queue;
7 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
8 | import org.springframework.context.annotation.Bean;
9 | import org.springframework.context.annotation.Configuration;
10 | import pl.kubaretip.chatservice.messaging.sender.DeleteMessagesSender;
11 |
12 | @Configuration
13 | public class RabbitMQConfig {
14 |
15 | @Bean
16 | public FanoutExchange fanoutExchange() {
17 | return new FanoutExchange("pl.kubaretip.authservice.fanout");
18 | }
19 |
20 | @Bean
21 | public Queue newUsersQueue() {
22 | return new Queue("pl.kubaretip.chatservice.account");
23 | }
24 |
25 | @Bean
26 | public Binding bindingActivationMail(FanoutExchange fanoutExchange, Queue newUsersQueue) {
27 | return BindingBuilder.bind(newUsersQueue).to(fanoutExchange);
28 | }
29 |
30 | @Bean
31 | public FanoutExchange deletingMessageExchange() {
32 | return new FanoutExchange("pl.kubaretip.chatmessagesservice.fanout.deleting");
33 | }
34 |
35 | @Bean
36 | public DeleteMessagesSender deleteMessagesSender(RabbitTemplate rabbitTemplate, FanoutExchange deletingMessageExchange) {
37 | return new DeleteMessagesSender(rabbitTemplate, deletingMessageExchange);
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/dto-models/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spring-micro-websocket-chat
7 | pl.kubaretip
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | dto-models
13 |
14 |
15 | 2.12.1
16 |
17 |
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-validation
23 |
24 |
25 |
26 | com.fasterxml.jackson.core
27 | jackson-annotations
28 | ${jackson-annotations.version}
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | org.springframework.boot
37 | spring-boot-maven-plugin
38 |
39 | true
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/chat-messages-service/src/main/java/pl/kubaretip/chatmessagesservice/security/JWTAuthenticationManager.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatmessagesservice.security;
2 |
3 | import com.auth0.jwt.exceptions.JWTDecodeException;
4 | import com.auth0.jwt.exceptions.TokenExpiredException;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.springframework.security.authentication.ReactiveAuthenticationManager;
7 | import org.springframework.security.core.Authentication;
8 | import org.springframework.stereotype.Component;
9 | import pl.kubaretip.authutils.jwt.JWTUtils;
10 | import reactor.core.publisher.Mono;
11 |
12 | @Slf4j
13 | @Component
14 | public class JWTAuthenticationManager implements ReactiveAuthenticationManager {
15 |
16 | private JWTUtils jwtUtils;
17 |
18 | public JWTAuthenticationManager(JWTUtils jwtUtils) {
19 | this.jwtUtils = jwtUtils;
20 | }
21 |
22 | @Override
23 | public Mono authenticate(Authentication authentication) {
24 |
25 | return Mono.just(authentication)
26 | .map(Authentication::getCredentials)
27 | .cast(String.class)
28 | .flatMap(token -> {
29 | log.debug("Authenticate {}" , token);
30 | try {
31 | return Mono.just(jwtUtils.getAuthentication(token));
32 | } catch (JWTDecodeException | TokenExpiredException ex) {
33 | log.error("Decode token exception");
34 | return Mono.empty();
35 | }
36 | });
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/repository/FriendRequestRepository.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.repository;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 | import org.springframework.data.jpa.repository.Modifying;
5 | import org.springframework.data.jpa.repository.Query;
6 | import pl.kubaretip.chatservice.domain.ChatProfile;
7 | import pl.kubaretip.chatservice.domain.FriendRequest;
8 |
9 | import java.util.List;
10 | import java.util.UUID;
11 |
12 | public interface FriendRequestRepository extends JpaRepository {
13 |
14 | @Query("SELECT " +
15 | "CASE WHEN COUNT(fr) > 0 THEN true ELSE false END " +
16 | "FROM FriendRequest fr WHERE (fr.sender = :user1 AND fr.recipient = :user2) " +
17 | "OR (fr.sender = :user2 AND fr.recipient = :user1)")
18 | boolean isFriendRequestAlreadyExists(ChatProfile user1, ChatProfile user2);
19 |
20 | @Query("SELECT fr FROM FriendRequest fr WHERE fr.recipient.userId = :recipientId AND fr.isAccepted = false")
21 | List findAllByRecipientIdAndNotAccepted(UUID recipientId);
22 |
23 | @Query("SELECT fr FROM FriendRequest fr WHERE fr.sender.userId = :senderId AND fr.isAccepted = false")
24 | List findAllBySenderIdAndNotAccepted(UUID senderId);
25 |
26 | @Modifying
27 | @Query("DELETE FROM FriendRequest WHERE (sender = :sender AND recipient = :recipient) " +
28 | "OR (sender = :recipient AND recipient = :sender)")
29 | void deleteFriendRequestByChatProfiles(ChatProfile sender, ChatProfile recipient);
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/messages-websocket-service/src/main/java/pl/kubaretip/messageswebsocketservice/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.messageswebsocketservice.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
6 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
7 | import org.springframework.security.config.http.SessionCreationPolicy;
8 | import pl.kubaretip.authutils.jwt.JWTConfig;
9 | import pl.kubaretip.authutils.jwt.JWTUtils;
10 |
11 | @EnableWebSecurity
12 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
13 |
14 | @Override
15 | protected void configure(HttpSecurity http) throws Exception {
16 | // @formatter:off
17 |
18 | http
19 | .cors()
20 | .and()
21 | .csrf()
22 | .disable()
23 | .sessionManagement()
24 | .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
25 | .and()
26 | .httpBasic()
27 | .disable()
28 | .authorizeRequests()
29 | .mvcMatchers("/ws").permitAll()
30 | .anyRequest()
31 | .authenticated();
32 |
33 | // @formatter:on
34 | }
35 |
36 | @Bean
37 | public JWTConfig jwtConfig() {
38 | return new JWTConfig();
39 | }
40 |
41 | @Bean
42 | public JWTUtils jwtUtils() {
43 | return new JWTUtils(jwtConfig());
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/security/AuthenticationSuccessHandler.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.security;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import org.springframework.http.MediaType;
5 | import org.springframework.security.core.Authentication;
6 | import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
7 | import org.springframework.stereotype.Component;
8 | import pl.kubaretip.authservice.security.model.TokenResponse;
9 |
10 | import javax.servlet.ServletException;
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 | import java.io.IOException;
14 | import java.nio.charset.StandardCharsets;
15 |
16 | @Component
17 | public class AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
18 |
19 | private final JWTBuilder jwtBuilder;
20 |
21 | public AuthenticationSuccessHandler(JWTBuilder jwtBuilder) {
22 | this.jwtBuilder = jwtBuilder;
23 | }
24 |
25 | @Override
26 | public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
27 | var out = response.getWriter();
28 | response.setContentType(MediaType.APPLICATION_JSON_VALUE);
29 | response.setCharacterEncoding(StandardCharsets.UTF_8.name());
30 | var token = jwtBuilder.buildToken(authentication);
31 | var tokenJson = new ObjectMapper().writeValueAsString(new TokenResponse(token));
32 | out.print(tokenJson);
33 | out.flush();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/security/JWTBuilder.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.security;
2 |
3 | import com.auth0.jwt.JWT;
4 | import com.auth0.jwt.algorithms.Algorithm;
5 | import org.springframework.security.core.Authentication;
6 | import org.springframework.security.core.GrantedAuthority;
7 | import pl.kubaretip.authutils.jwt.JWTConfig;
8 | import pl.kubaretip.authutils.security.SecurityUserDetailsImpl;
9 |
10 |
11 | import java.util.Date;
12 | import java.util.stream.Collectors;
13 |
14 | import static pl.kubaretip.authutils.jwt.JWTConstants.*;
15 |
16 | public class JWTBuilder {
17 |
18 | private final long tokenValidityTimeInMilliseconds;
19 | private final Algorithm sign;
20 |
21 | public JWTBuilder(JWTConfig jwtConfig) {
22 | this.tokenValidityTimeInMilliseconds = jwtConfig.getExpiration() * 1000L;
23 | this.sign = Algorithm.HMAC512(jwtConfig.getSecret());
24 | }
25 |
26 | public String buildToken(Authentication authentication) {
27 | var user = (SecurityUserDetailsImpl) authentication.getPrincipal();
28 | var authorities = user.getAuthorities()
29 | .stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
30 | var expiresAt = new Date(System.currentTimeMillis() + this.tokenValidityTimeInMilliseconds);
31 |
32 | return JWT.create()
33 | .withSubject(user.getId())
34 | .withExpiresAt(expiresAt)
35 | .withClaim(USERNAME_KEY, user.getUsername())
36 | .withClaim(AUTHORITIES_KEY, authorities)
37 | .sign(sign);
38 | }
39 |
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/security/AuthenticationFailureHandler.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.security;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import org.springframework.http.HttpStatus;
5 | import org.springframework.http.MediaType;
6 | import org.springframework.security.core.AuthenticationException;
7 | import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
8 | import pl.kubaretip.exceptionutils.error.Error;
9 |
10 | import javax.servlet.ServletException;
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 | import java.io.IOException;
14 | import java.nio.charset.StandardCharsets;
15 |
16 | public class AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
17 |
18 | @Override
19 | public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
20 | response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
21 | response.setContentType(MediaType.APPLICATION_JSON_VALUE);
22 | response.setCharacterEncoding(StandardCharsets.UTF_8.name());
23 | var out = response.getWriter();
24 |
25 | var error = Error.builder()
26 | .status(HttpStatus.UNAUTHORIZED.value())
27 | .detail(exception.getMessage())
28 | .title(HttpStatus.UNAUTHORIZED.getReasonPhrase())
29 | .build();
30 |
31 | var jsonErrorResponse = new ObjectMapper().writeValueAsString(error);
32 | out.print(jsonErrorResponse);
33 | out.flush();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/auth-utils/src/main/java/pl/kubaretip/authutils/jwt/JWTFilter.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authutils.jwt;
2 |
3 | import com.auth0.jwt.exceptions.JWTDecodeException;
4 | import com.auth0.jwt.exceptions.TokenExpiredException;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.springframework.security.core.context.SecurityContextHolder;
7 | import org.springframework.web.filter.OncePerRequestFilter;
8 |
9 | import javax.servlet.FilterChain;
10 | import javax.servlet.ServletException;
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 | import java.io.IOException;
14 |
15 | @Slf4j
16 | public class JWTFilter extends OncePerRequestFilter {
17 |
18 | private final JWTUtils jwtUtils;
19 |
20 | public JWTFilter(JWTUtils jwtUtils) {
21 | this.jwtUtils = jwtUtils;
22 | }
23 |
24 | @Override
25 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
26 | var authorizationHeaderValue = request.getHeader(jwtUtils.getJwtConfig().getHeader());
27 | if (jwtUtils.isValidAuthorizationHeaderValue(authorizationHeaderValue)) {
28 | var token = authorizationHeaderValue.replace(jwtUtils.getJwtConfig().getTokenPrefix(), "");
29 | try {
30 | var authentication = jwtUtils.getAuthentication(token);
31 | SecurityContextHolder.getContext().setAuthentication(authentication);
32 | } catch (JWTDecodeException | TokenExpiredException ex) {
33 | SecurityContextHolder.clearContext();
34 | }
35 | }
36 | chain.doFilter(request, response);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/dto-models/src/main/java/pl/kubaretip/dtomodels/UserDTO.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.dtomodels;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import lombok.Getter;
6 | import lombok.NoArgsConstructor;
7 | import lombok.Setter;
8 |
9 | import javax.validation.constraints.Email;
10 | import javax.validation.constraints.NotBlank;
11 | import javax.validation.constraints.Pattern;
12 | import javax.validation.constraints.Size;
13 | import java.io.Serializable;
14 |
15 | @JsonInclude(JsonInclude.Include.NON_NULL)
16 | @Getter
17 | @Setter
18 | @NoArgsConstructor
19 | public class UserDTO implements Serializable {
20 |
21 | private String id;
22 |
23 | @NotBlank
24 | @Size(min = 4, max = 50)
25 | @Pattern(regexp = "^[a-zA-Z0-9]*$")
26 | private String username;
27 |
28 | @JsonProperty(value = "password", access = JsonProperty.Access.WRITE_ONLY)
29 | @NotBlank
30 | @Size(min = 6, max = 32)
31 | private String password;
32 |
33 | @Pattern(regexp = "^[a-zA-Z]*$")
34 | @Size(min = 2, max = 50)
35 | @NotBlank
36 | private String firstName;
37 |
38 | @Pattern(regexp = "^[a-zA-Z]*$")
39 | @Size(min = 2, max = 50)
40 | @NotBlank
41 | private String lastName;
42 |
43 | @Email
44 | @NotBlank
45 | private String email;
46 |
47 | private String activationKey;
48 |
49 |
50 | public UserDTO(String username, String password, String firstName, String lastName, String email) {
51 | this.username = username;
52 | this.password = password;
53 | this.firstName = firstName;
54 | this.lastName = lastName;
55 | this.email = email;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/messages-websocket-service/src/main/java/pl/kubaretip/messageswebsocketservice/security/AuthChannelInterceptor.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.messageswebsocketservice.security;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.http.HttpHeaders;
5 | import org.springframework.messaging.Message;
6 | import org.springframework.messaging.MessageChannel;
7 | import org.springframework.messaging.simp.stomp.StompCommand;
8 | import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
9 | import org.springframework.messaging.support.ChannelInterceptor;
10 | import org.springframework.messaging.support.MessageHeaderAccessor;
11 | import org.springframework.stereotype.Component;
12 |
13 | @Slf4j
14 | @Component
15 | public class AuthChannelInterceptor implements ChannelInterceptor {
16 |
17 | private final WebSocketAuthService webSocketAuthService;
18 |
19 | public AuthChannelInterceptor(WebSocketAuthService webSocketAuthService) {
20 | this.webSocketAuthService = webSocketAuthService;
21 | }
22 |
23 | @Override
24 | public Message> preSend(Message> message, MessageChannel channel) {
25 | var accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
26 |
27 | if (accessor != null && StompCommand.CONNECT.equals(accessor.getCommand())) {
28 | var authorizationHeaderValue = (String) accessor.getFirstNativeHeader(HttpHeaders.AUTHORIZATION);
29 | final var authenticationToken = webSocketAuthService.attemptAuthentication(authorizationHeaderValue);
30 |
31 | if (authenticationToken != null)
32 | accessor.setUser(authenticationToken);
33 | }
34 |
35 | return message;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/exception-utils/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spring-micro-websocket-chat
7 | pl.kubaretip
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | exception-utils
13 |
14 | 4.0.1
15 |
16 |
17 |
18 |
19 | com.fasterxml.jackson.core
20 | jackson-annotations
21 |
22 |
23 | org.springframework
24 | spring-web
25 |
26 |
27 | javax.servlet
28 | javax.servlet-api
29 | ${javax.servlet-api.version}
30 | provided
31 |
32 |
33 |
34 |
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-maven-plugin
39 |
40 | true
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/security/JWTAuthenticationFilter.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.security;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
6 | import org.springframework.security.core.Authentication;
7 | import org.springframework.security.core.AuthenticationException;
8 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
9 | import pl.kubaretip.authservice.exception.InvalidAuthenticationRequestException;
10 | import pl.kubaretip.authservice.security.model.AuthRequestModel;
11 |
12 | import javax.servlet.http.HttpServletRequest;
13 | import javax.servlet.http.HttpServletResponse;
14 | import java.io.IOException;
15 |
16 | @Slf4j
17 | public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
18 |
19 | @Override
20 | public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
21 | AuthRequestModel authenticationRequest;
22 | try {
23 | authenticationRequest = new ObjectMapper().readValue(request.getInputStream(), AuthRequestModel.class);
24 | } catch (IOException e) {
25 | throw new InvalidAuthenticationRequestException("Invalid login request");
26 | }
27 | log.debug("Attempt authentication user: " + authenticationRequest.getUsername());
28 | var authentication = new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword());
29 | return this.getAuthenticationManager().authenticate(authentication);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/chat-messages-service/src/main/java/pl/kubaretip/chatmessagesservice/security/JWTAuthenticationConverter.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatmessagesservice.security;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.http.HttpHeaders;
5 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
6 | import org.springframework.security.core.Authentication;
7 | import org.springframework.security.web.server.authentication.ServerAuthenticationConverter;
8 | import org.springframework.stereotype.Component;
9 | import org.springframework.web.server.ServerWebExchange;
10 | import pl.kubaretip.authutils.jwt.JWTUtils;
11 | import reactor.core.publisher.Mono;
12 |
13 | @Slf4j
14 | @Component
15 | public class JWTAuthenticationConverter implements ServerAuthenticationConverter {
16 |
17 | private final JWTUtils jwtUtils;
18 |
19 | public JWTAuthenticationConverter(JWTUtils jwtUtils) {
20 | this.jwtUtils = jwtUtils;
21 | }
22 |
23 | @Override
24 | public Mono convert(ServerWebExchange exchange) {
25 |
26 | return Mono.justOrEmpty(exchange.getRequest().getHeaders())
27 | .flatMap(headers -> Mono.justOrEmpty(headers.getFirst(HttpHeaders.AUTHORIZATION)))
28 | .flatMap(authHeaderValue -> {
29 | if (jwtUtils.isValidAuthorizationHeaderValue(authHeaderValue)) {
30 | var token = authHeaderValue.replace(jwtUtils.getJwtConfig().getTokenPrefix(), "");
31 | log.debug("Token {}", token);
32 | return Mono.just(new UsernamePasswordAuthenticationToken(token, token));
33 | } else
34 | return Mono.empty();
35 | });
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/auth-service/src/test/java/pl/kubaretip/authservice/utils/SpringSecurityWebTestConfig.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.utils;
2 |
3 | import org.springframework.boot.test.context.TestConfiguration;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Primary;
6 | import org.springframework.security.core.userdetails.UserDetailsService;
7 | import pl.kubaretip.authservice.domain.Authority;
8 | import pl.kubaretip.authservice.domain.User;
9 | import pl.kubaretip.authservice.repository.UserRepository;
10 | import pl.kubaretip.authservice.security.UserDetailsServiceImpl;
11 |
12 | import java.util.Collections;
13 | import java.util.Optional;
14 | import java.util.UUID;
15 |
16 | import static org.mockito.ArgumentMatchers.anyString;
17 | import static org.mockito.BDDMockito.given;
18 | import static org.mockito.Mockito.mock;
19 |
20 |
21 | @TestConfiguration
22 | public class SpringSecurityWebTestConfig {
23 |
24 | @Bean
25 | @Primary
26 | public UserDetailsService customUserDetailsService() {
27 |
28 | var userRepositoryMock = mock(UserRepository.class);
29 |
30 | var user = new User();
31 | user.setId(UUID.fromString("1062d618-64f6-401c-ab7c-ef050eb6f4b2"));
32 | user.setUsername("testUser");
33 | user.setFirstName("userFirstName");
34 | user.setLastName("userLastName");
35 | user.setEnabled(true);
36 | user.setPassword("password");
37 | var authority = new Authority();
38 | authority.setName("ROLE_USER");
39 | user.setAuthorities(Collections.singleton(authority));
40 |
41 | given(userRepositoryMock.findOneWithAuthoritiesByUsernameIgnoreCase(anyString())).willReturn(Optional.of(user));
42 |
43 | return new UserDetailsServiceImpl(userRepositoryMock);
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/security/UserDetailsServiceImpl.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.security;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
5 | import org.springframework.security.core.userdetails.UserDetails;
6 | import org.springframework.security.core.userdetails.UserDetailsService;
7 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
8 | import org.springframework.stereotype.Service;
9 | import pl.kubaretip.authservice.repository.UserRepository;
10 | import pl.kubaretip.authutils.security.SecurityUserDetailsImpl;
11 |
12 | import javax.transaction.Transactional;
13 | import java.util.stream.Collectors;
14 |
15 | @Slf4j
16 | @Service
17 | public class UserDetailsServiceImpl implements UserDetailsService {
18 |
19 | private final UserRepository userRepository;
20 |
21 | public UserDetailsServiceImpl(UserRepository userRepository) {
22 | this.userRepository = userRepository;
23 | }
24 |
25 | @Transactional
26 | @Override
27 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
28 | log.debug("Fetching given user {}", username);
29 |
30 | return userRepository.findOneWithAuthoritiesByUsernameIgnoreCase(username)
31 | .map(user -> new SecurityUserDetailsImpl(user.getId().toString(),
32 | user.getUsername(), user.getPassword(), user.getEnabled(),
33 | user.getAuthorities().stream()
34 | .map(authority -> new SimpleGrantedAuthority(authority.getName()))
35 | .collect(Collectors.toList()))
36 | ).orElseThrow(() -> new UsernameNotFoundException("User " + username + " not found"));
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/cloud-gateway/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spring-micro-websocket-chat
7 | pl.kubaretip
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | cloud-gateway
13 |
14 |
15 |
16 |
17 | org.springframework.cloud
18 | spring-cloud-starter-gateway
19 |
20 |
21 |
22 | org.springframework.cloud
23 | spring-cloud-starter-netflix-eureka-client
24 |
25 |
26 |
27 | org.springframework.cloud
28 | spring-cloud-starter-config
29 |
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-actuator
34 |
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-aop
39 |
40 |
41 |
42 | org.springframework.retry
43 | spring-retry
44 |
45 |
46 |
47 | org.springdoc
48 | springdoc-openapi-webflux-ui
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/web/rest/ChatProfileController.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.web.rest;
2 |
3 | import org.springframework.http.ResponseEntity;
4 | import org.springframework.web.bind.annotation.*;
5 | import pl.kubaretip.authutils.SecurityUtils;
6 | import pl.kubaretip.chatservice.dto.ChatProfileDTO;
7 | import pl.kubaretip.chatservice.dto.mapper.ChatProfileMapper;
8 | import pl.kubaretip.chatservice.service.ChatProfileService;
9 | import pl.kubaretip.exceptionutils.InvalidDataException;
10 |
11 | @RestController
12 | @RequestMapping("/chat-profiles")
13 | public class ChatProfileController {
14 |
15 | private final ChatProfileService chatProfileService;
16 | private final ChatProfileMapper chatProfileMapper;
17 |
18 | public ChatProfileController(ChatProfileService chatProfileService,
19 | ChatProfileMapper chatProfileMapper) {
20 | this.chatProfileService = chatProfileService;
21 | this.chatProfileMapper = chatProfileMapper;
22 | }
23 |
24 | @GetMapping("/{id}")
25 | public ResponseEntity getChatProfileById(@PathVariable("id") String id) {
26 | return ResponseEntity.ok()
27 | .body(chatProfileMapper.chatProfileToChatProfileDTO(chatProfileService.getChatProfileById(id)));
28 | }
29 |
30 | @PatchMapping("/{id}/new-friends-request-code")
31 | public ResponseEntity generateNewFriendsRequestCode(@PathVariable("id") String userId) {
32 |
33 | if (!userId.equals(SecurityUtils.getCurrentUser())) {
34 | throw new InvalidDataException("Invalid user id");
35 | }
36 | var chatProfile = chatProfileService.generateNewFriendsRequestCode(userId, SecurityUtils.getCurrentUserPreferredUsername());
37 | return ResponseEntity.ok()
38 | .body(chatProfileMapper.chatProfileToChatProfileDTO(chatProfile));
39 | }
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/dto/mapper/FriendRequestMapper.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.dto.mapper;
2 |
3 | import org.mapstruct.*;
4 | import pl.kubaretip.chatservice.domain.FriendRequest;
5 | import pl.kubaretip.chatservice.dto.FriendRequestDTO;
6 | import pl.kubaretip.chatservice.util.DateUtils;
7 |
8 | import java.time.OffsetDateTime;
9 | import java.time.format.DateTimeFormatter;
10 | import java.util.List;
11 |
12 |
13 | @Mapper(componentModel = "spring", uses = ChatProfileMapper.class)
14 | public interface FriendRequestMapper {
15 |
16 | @Mapping(target = "sender", qualifiedByName = "chatProfileToChatProfileDTO")
17 | @Mapping(target = "recipient", qualifiedByName = "chatProfileToChatProfileDTO")
18 | @Mapping(target = "sentTime", expression = "java(convertOffsetDateToString(friendRequest.getSentTime()))")
19 | FriendRequestDTO mapToFriendRequestDTO(FriendRequest friendRequest);
20 |
21 | @Named("mapWithoutRecipient")
22 | @InheritConfiguration(name = "mapToFriendRequestDTO")
23 | @Mapping(target = "recipient", ignore = true)
24 | FriendRequestDTO mapToFriendRequestDTOWithoutRecipient(FriendRequest friendRequest);
25 |
26 | @Named("mapWithoutSender")
27 | @InheritConfiguration(name = "mapToFriendRequestDTO")
28 | @Mapping(target = "sender", ignore = true)
29 | FriendRequestDTO mapToFriendRequestDTOWithoutSender(FriendRequest friendRequest);
30 |
31 | @IterableMapping(qualifiedByName = "mapWithoutRecipient")
32 | List mapToFriendRequestDTOListWithoutRecipient(List friendRequests);
33 |
34 | @IterableMapping(qualifiedByName = "mapWithoutSender")
35 | List mapToFriendRequestDTOListWithoutSender(List friendRequests);
36 |
37 |
38 | default String convertOffsetDateToString(OffsetDateTime time) {
39 | return time.format(DateTimeFormatter.ofPattern(DateUtils.DATE_PATTERN));
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/exception-utils/src/main/java/pl/kubaretip/exceptionutils/CommonExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.exceptionutils;
2 |
3 | import org.springframework.http.HttpStatus;
4 | import org.springframework.web.bind.annotation.ExceptionHandler;
5 | import org.springframework.web.bind.annotation.ResponseStatus;
6 | import pl.kubaretip.exceptionutils.error.Error;
7 |
8 | import javax.servlet.http.HttpServletRequest;
9 |
10 | public interface CommonExceptionHandler {
11 |
12 | @ExceptionHandler(value = {NotFoundException.class})
13 | @ResponseStatus(HttpStatus.NOT_FOUND)
14 | default Error handleNotFound(final NotFoundException ex, HttpServletRequest request) {
15 | return Error.builder()
16 | .status(HttpStatus.NOT_FOUND.value())
17 | .detail(ex.getMessage())
18 | .path(request.getRequestURI())
19 | .title(HttpStatus.NOT_FOUND.getReasonPhrase())
20 | .build();
21 | }
22 |
23 | @ExceptionHandler(value = {AlreadyExistsException.class})
24 | @ResponseStatus(HttpStatus.CONFLICT)
25 | default Error handleAlreadyExists(final AlreadyExistsException ex, HttpServletRequest request) {
26 | return Error.builder()
27 | .status(HttpStatus.CONFLICT.value())
28 | .detail(ex.getMessage())
29 | .path(request.getRequestURI())
30 | .title(HttpStatus.CONFLICT.getReasonPhrase())
31 | .build();
32 | }
33 |
34 | @ExceptionHandler(value = {InvalidDataException.class})
35 | @ResponseStatus(HttpStatus.BAD_REQUEST)
36 | default Error handleInvalidData(final InvalidDataException ex, HttpServletRequest request) {
37 | return Error.builder()
38 | .status(HttpStatus.BAD_REQUEST.value())
39 | .detail(ex.getMessage())
40 | .path(request.getRequestURI())
41 | .title(HttpStatus.BAD_REQUEST.getReasonPhrase())
42 | .build();
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/cloud-gateway/src/main/java/pl/kubaretip/cloudgateway/config/CorsConfig.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.cloudgateway.config;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.web.cors.CorsConfiguration;
7 | import org.springframework.web.cors.reactive.CorsWebFilter;
8 | import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
9 | import org.springframework.web.reactive.config.CorsRegistry;
10 | import org.springframework.web.reactive.config.EnableWebFlux;
11 | import org.springframework.web.reactive.config.WebFluxConfigurer;
12 |
13 | import java.util.Arrays;
14 |
15 | @EnableWebFlux
16 | @Configuration
17 | public class CorsConfig implements WebFluxConfigurer {
18 |
19 |
20 | @Value("${cors.allowed-origins:*}")
21 | private String[] allowedOrigins;
22 |
23 | @Value("${cors.allowed-headers:*}")
24 | private String[] allowedHeaders;
25 |
26 | @Value("${allowed-methods:*}")
27 | private String[] allowedMethods;
28 |
29 | @Override
30 | public void addCorsMappings(CorsRegistry registry) {
31 | registry.addMapping("/**")
32 | .allowedOrigins(allowedOrigins)
33 | .allowedHeaders(allowedHeaders)
34 | .allowedMethods(allowedMethods);
35 | }
36 |
37 | @Bean
38 | public CorsWebFilter corsWebFilter() {
39 | var corsConfiguration = new CorsConfiguration();
40 | corsConfiguration.setAllowedHeaders(Arrays.asList(allowedHeaders));
41 | corsConfiguration.setAllowedMethods(Arrays.asList(allowedMethods));
42 | corsConfiguration.setAllowedOrigins(Arrays.asList(allowedOrigins));
43 |
44 | var corsConfigurationSource = new UrlBasedCorsConfigurationSource();
45 | corsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
46 |
47 | return new CorsWebFilter(corsConfigurationSource);
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/auth-utils/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spring-micro-websocket-chat
7 | pl.kubaretip
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 | jar
12 | auth-utils
13 |
14 |
15 | 5.4.5
16 | 4.0.1
17 |
18 |
19 |
20 |
21 |
22 | javax.servlet
23 | javax.servlet-api
24 | ${javax.servlet-api.version}
25 | provided
26 |
27 |
28 |
29 | com.auth0
30 | java-jwt
31 |
32 |
33 |
34 | org.springframework.security
35 | spring-security-core
36 |
37 |
38 |
39 | org.springframework
40 | spring-web
41 |
42 |
43 |
44 | org.slf4j
45 | slf4j-api
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | org.springframework.boot
54 | spring-boot-maven-plugin
55 |
56 | true
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/auth-utils/src/main/java/pl/kubaretip/authutils/security/SecurityUserDetailsImpl.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authutils.security;
2 |
3 | import org.springframework.security.core.GrantedAuthority;
4 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
5 |
6 | import java.util.Collection;
7 | import java.util.List;
8 |
9 | public class SecurityUserDetailsImpl implements SecurityUserDetails {
10 |
11 | private final String username;
12 | private final String password;
13 | private final String id;
14 | private final Collection extends GrantedAuthority> authorities;
15 | private final boolean enabled;
16 |
17 | public SecurityUserDetailsImpl(String id, String username, String password, boolean enabled, List authorities) {
18 | this.username = username;
19 | this.password = password;
20 | this.id = id;
21 | this.authorities = authorities;
22 | this.enabled = enabled;
23 | }
24 |
25 | public SecurityUserDetailsImpl(String id, String username, String password, Collection extends GrantedAuthority> authorities) {
26 | this.username = username;
27 | this.password = password;
28 | this.id = id;
29 | this.authorities = authorities;
30 | this.enabled = true;
31 | }
32 |
33 | @Override
34 | public Collection extends GrantedAuthority> getAuthorities() {
35 | return this.authorities;
36 | }
37 |
38 | @Override
39 | public String getPassword() {
40 | return this.password;
41 | }
42 |
43 | @Override
44 | public String getUsername() {
45 | return this.username;
46 | }
47 |
48 | @Override
49 | public boolean isAccountNonExpired() {
50 | return true;
51 | }
52 |
53 | @Override
54 | public boolean isAccountNonLocked() {
55 | return true;
56 | }
57 |
58 | @Override
59 | public boolean isCredentialsNonExpired() {
60 | return true;
61 | }
62 |
63 | @Override
64 | public boolean isEnabled() {
65 | return this.enabled;
66 | }
67 |
68 | @Override
69 | public String getId() {
70 | return id;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/auth-utils/src/main/java/pl/kubaretip/authutils/jwt/JWTUtils.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authutils.jwt;
2 |
3 | import com.auth0.jwt.JWT;
4 | import com.auth0.jwt.algorithms.Algorithm;
5 | import org.apache.commons.lang3.StringUtils;
6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
7 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
8 | import pl.kubaretip.authutils.security.SecurityUserDetailsImpl;
9 |
10 | import java.util.stream.Collectors;
11 |
12 | import static pl.kubaretip.authutils.jwt.JWTConstants.*;
13 |
14 | public class JWTUtils {
15 |
16 | private final Algorithm sign;
17 | private final JWTConfig jwtConfig;
18 |
19 | public JWTUtils(JWTConfig jwtConfig) {
20 | this.jwtConfig = jwtConfig;
21 | this.sign = Algorithm.HMAC512(jwtConfig.getSecret());
22 | }
23 |
24 | public boolean isValidAuthorizationHeaderValue(String authHeaderValue) {
25 | return StringUtils.isNotBlank(authHeaderValue)
26 | && authHeaderValue.contains(jwtConfig.getTokenPrefix())
27 | && StringUtils.isNotBlank(authHeaderValue.replace(jwtConfig.getTokenPrefix(), ""));
28 | }
29 |
30 | public UsernamePasswordAuthenticationToken getAuthentication(String token) {
31 |
32 | var decodedJWT = JWT
33 | .require(sign)
34 | .build()
35 | .verify(token);
36 |
37 | if (decodedJWT != null) {
38 | var authorities = decodedJWT.getClaim(AUTHORITIES_KEY)
39 | .asList(String.class)
40 | .stream()
41 | .map(SimpleGrantedAuthority::new)
42 | .collect(Collectors.toList());
43 |
44 | var userId = decodedJWT.getSubject();
45 | var username = decodedJWT.getClaim(USERNAME_KEY).asString();
46 | var securityUser = new SecurityUserDetailsImpl(userId, username, "", authorities);
47 |
48 | return new UsernamePasswordAuthenticationToken(securityUser, token, authorities);
49 |
50 | }
51 | return null;
52 | }
53 |
54 | public JWTConfig getJwtConfig() {
55 | return jwtConfig;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/chat-service/src/main/java/pl/kubaretip/chatservice/web/rest/FriendChatController.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.chatservice.web.rest;
2 |
3 | import org.springframework.http.ResponseEntity;
4 | import org.springframework.web.bind.annotation.*;
5 | import pl.kubaretip.authutils.SecurityUtils;
6 | import pl.kubaretip.chatservice.dto.FriendChatDTO;
7 | import pl.kubaretip.chatservice.dto.mapper.FriendChatMapper;
8 | import pl.kubaretip.chatservice.messaging.sender.DeleteMessagesSender;
9 | import pl.kubaretip.chatservice.service.FriendChatService;
10 |
11 | import java.util.List;
12 |
13 | @RestController
14 | @RequestMapping("/friends-chats")
15 | public class FriendChatController {
16 |
17 | private final FriendChatService friendChatService;
18 | private final FriendChatMapper friendChatMapper;
19 | private final DeleteMessagesSender deleteMessagesSender;
20 |
21 | public FriendChatController(FriendChatService friendChatService,
22 | FriendChatMapper friendChatMapper,
23 | DeleteMessagesSender deleteMessagesSender) {
24 | this.friendChatService = friendChatService;
25 | this.friendChatMapper = friendChatMapper;
26 | this.deleteMessagesSender = deleteMessagesSender;
27 | }
28 |
29 | @GetMapping
30 | public ResponseEntity> getAllFriendsChats() {
31 |
32 | var allFriendsChatsBySender = friendChatService.getAllFriendsChatsBySender(SecurityUtils.getCurrentUser());
33 |
34 | return ResponseEntity.ok()
35 | .body(friendChatMapper.mapToFriendChatList(allFriendsChatsBySender));
36 | }
37 |
38 | @DeleteMapping(params = {"friend_chat", "friend_chat_with"})
39 | public ResponseEntity deleteUserFriendChat(@RequestParam("friend_chat") long friendChatId,
40 | @RequestParam("friend_chat_with") long friendChatWithId) {
41 | friendChatService.deleteFriendChat(friendChatId, friendChatWithId, SecurityUtils.getCurrentUser());
42 | deleteMessagesSender.sendDeletingMessagesTask(List.of(friendChatId, friendChatWithId));
43 | return ResponseEntity.noContent().build();
44 | }
45 |
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/cloud-gateway/src/main/java/pl/kubaretip/cloudgateway/config/CloudConfig.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.cloudgateway.config;
2 |
3 | import org.springframework.cloud.gateway.route.RouteLocator;
4 | import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | @Configuration
9 | public class CloudConfig {
10 |
11 | @Bean
12 | public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
13 |
14 | return builder.routes()
15 | .route(predicateSpec -> predicateSpec.path("/auth-service/**")
16 | .filters(f -> f.rewritePath("/auth-service/(?.*)", "/${remaining}"))
17 | .uri("lb://AUTH")
18 | .id("AUTH")
19 | )
20 | .route(predicateSpec -> predicateSpec.path("/chat-service/**")
21 | .filters(f -> f.rewritePath("/chat-service/(?.*)", "/${remaining}"))
22 | .uri("lb://CHAT")
23 | .id("CHAT")
24 | )
25 | .route(predicateSpec -> predicateSpec.path("/chat-messages-service/**")
26 | .filters(f -> f.rewritePath("/chat-messages-service/(?.*)", "/${remaining}"))
27 | .uri("lb://CHAT-MESSAGES")
28 | .id("CHAT-MESSAGES")
29 | )
30 | .route(predicateSpec -> predicateSpec.path("/messages-websocket-service/**")
31 | .filters(f -> f.rewritePath("/messages-websocket-service/(?.*)", "/${remaining}"))
32 | .uri("lb://MESSAGES-WEBSOCKET")
33 | .id("MESSAGES-WEBSOCKET")
34 | )
35 | .route(predicateSpec -> predicateSpec.path("/v3/api-docs/**")
36 | .filters(f -> f.rewritePath("/v3/api-docs/(?.*)", "/${path}/v3/api-docs"))
37 | .uri("http://localhost:8080")
38 | .id("openapi")
39 | )
40 | .build();
41 | }
42 |
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/web/rest/AuthorizationController.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.web.rest;
2 |
3 | import io.swagger.v3.oas.annotations.Operation;
4 | import io.swagger.v3.oas.annotations.Parameter;
5 | import io.swagger.v3.oas.annotations.media.ArraySchema;
6 | import io.swagger.v3.oas.annotations.media.Content;
7 | import io.swagger.v3.oas.annotations.media.Schema;
8 | import io.swagger.v3.oas.annotations.responses.ApiResponse;
9 | import io.swagger.v3.oas.annotations.responses.ApiResponses;
10 | import io.swagger.v3.oas.annotations.tags.Tag;
11 | import org.springframework.http.MediaType;
12 | import org.springframework.web.bind.annotation.PostMapping;
13 | import org.springframework.web.bind.annotation.RequestBody;
14 | import org.springframework.web.bind.annotation.RequestMapping;
15 | import org.springframework.web.bind.annotation.RestController;
16 | import pl.kubaretip.authservice.security.model.AuthRequestModel;
17 | import pl.kubaretip.authservice.security.model.TokenResponse;
18 |
19 | /**
20 | * Authentication API spec for Swagger doc
21 | * Implemented and automatically overridden by Spring Security filters.
22 | * Request mapping value coming from JWTConfig class
23 | *
24 | * @see pl.kubaretip.authutils.jwt.JWTConfig
25 | */
26 | @Tag(name = "Authorization", description = "Login endpoint")
27 | @RequestMapping(value = "/authenticate", produces = MediaType.APPLICATION_JSON_VALUE)
28 | @RestController
29 | public class AuthorizationController {
30 |
31 | @Operation(summary = "Login", description = "Generating JWT tokens", tags = {"Authorization"})
32 | @PostMapping
33 | @ApiResponses({
34 | @ApiResponse(responseCode = "200", description = "JWT token",
35 | content = @Content(array = @ArraySchema(schema = @Schema(implementation = TokenResponse.class)))),
36 | @ApiResponse(responseCode = "401", description = "Unauthorized")
37 | })
38 | public void fakeLogin(@Parameter(description = "Username and password",
39 | required = true, schema = @Schema(implementation = AuthRequestModel.class))
40 | @RequestBody AuthRequestModel authRequestModel) {
41 | throw new IllegalStateException("Should not be called ! Implemented by Spring Security filters.");
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/docker/docker-compose-dev.yml:
--------------------------------------------------------------------------------
1 | version: '3.8'
2 |
3 | volumes:
4 | mysql_auth:
5 | name: auth_service_vol
6 | driver: local
7 | mongo_chat:
8 | name: chat_messages_service_vol
9 | driver: local
10 | mysql_chat:
11 | name: chat_service_vol
12 | driver: local
13 | rabbitmq:
14 | name: rabbitmq_vol
15 | driver: local
16 |
17 | services:
18 | auth_db:
19 | container_name: auth_service_mysql
20 | image: library/mysql:8.0.22
21 | environment:
22 | MYSQL_DATABASE: auth_service_database
23 | MYSQL_USER: ${AUTH_SERVICE_MYSQL_USER}
24 | MYSQL_PASSWORD: ${AUTH_SERVICE_MYSQL_PASS}
25 | MYSQL_ROOT_PASSWORD: ${AUTH_SERVICE_MYSQL_ROOT_PASS}
26 | ports:
27 | - 3306:3306
28 | volumes:
29 | - mysql_auth:/var/lib/mysql
30 | messages_db:
31 | container_name: chat_messages_service_mongo
32 | image: library/mongo:latest
33 | environment:
34 | MONGO_INITDB_DATABASE: chat_messages_service_database
35 | MONGO_INITDB_ROOT_USERNAME: ${CHAT_MESSAGES_SERVICE_ROOT_MONGO_USER}
36 | MONGO_INITDB_ROOT_PASSWORD: ${CHAT_MESSAGES_SERVICE_ROOT_MONGO_PASS}
37 | ports:
38 | - 27017:27017
39 | volumes:
40 | - mongo_chat:/var/lib/mongo
41 | - ./init-chat-messages-service-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
42 | chat_db:
43 | container_name: chat_service_mysql
44 | image: library/mysql:8.0.22
45 | environment:
46 | MYSQL_DATABASE: chat_service_database
47 | MYSQL_USER: ${CHAT_SERVICE_MYSQL_USER}
48 | MYSQL_PASSWORD: ${CHAT_SERVICE_MYSQL_PASS}
49 | MYSQL_ROOT_PASSWORD: ${CHAT_SERVICE_MYSQL_ROOT_PASS}
50 | ports:
51 | - 3307:3306
52 | volumes:
53 | - mysql_chat:/var/lib/mysql
54 | rabbitmq:
55 | container_name: rabbitmq-service
56 | image: rabbitmq:3-management
57 | command: sh -c "rabbitmq-plugins enable rabbitmq_stomp; rabbitmq-server"
58 | ports:
59 | - 5672:5672
60 | - 15672:15672
61 | - 61613:61613
62 | volumes:
63 | - rabbitmq:/etc/rabbitmq/
64 | - rabbitmq:/var/lib/rabbitmq/
65 | - rabbitmq:/var/log/rabbitmq/
66 | - ./rabbitmq-isolated.conf:/etc/rabbitmq/rabbitmq.config
67 | # Mail catcher for local debugging
68 | mailhog:
69 | image: mailhog/mailhog
70 | container_name: mailhog
71 | ports:
72 | - 1025:1025 # smtp port
73 | - 8025:8025 # web ui port
--------------------------------------------------------------------------------
/auth-service/src/main/java/pl/kubaretip/authservice/exception/controllerAdvice/ValidationExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package pl.kubaretip.authservice.exception.controllerAdvice;
2 |
3 | import org.springframework.http.HttpHeaders;
4 | import org.springframework.http.HttpStatus;
5 | import org.springframework.http.ResponseEntity;
6 | import org.springframework.web.bind.MethodArgumentNotValidException;
7 | import org.springframework.web.bind.annotation.ControllerAdvice;
8 | import org.springframework.web.context.request.WebRequest;
9 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
10 | import pl.kubaretip.exceptionutils.error.Error;
11 | import pl.kubaretip.exceptionutils.error.Violation;
12 |
13 | import java.util.ArrayList;
14 | import java.util.Collections;
15 | import java.util.HashSet;
16 | import java.util.Set;
17 |
18 | @ControllerAdvice
19 | public class ValidationExceptionHandler extends ResponseEntityExceptionHandler {
20 |
21 | @Override
22 | protected ResponseEntity