Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chat 199 ws client integration #60

Merged
merged 6 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ public void configureMessageBroker(MessageBrokerRegistry registry) {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint(properties.getEndpoint());
registry.addEndpoint(properties.getEndpoint()).withSockJS();
registry.addEndpoint(properties.getEndpoint()).setAllowedOriginPatterns("*").withSockJS();
}
}
9 changes: 7 additions & 2 deletions src/main/java/com/chat/yourway/security/JwtAuthFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ protected void doFilterInternal(@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) throws ServletException, IOException {

if (isNotAuthorizationHeader(request)) {
logger.warn("Header does not contain " + AUTHORIZATION);
if (isNotAuthorizationHeader(request) && isNotTokenParameter(request)) {
log.warn("Request without authorization. Header or parameter does not contain {}",
AUTHORIZATION);
filterChain.doFilter(request, response);
return;
}
Expand Down Expand Up @@ -85,4 +86,8 @@ private boolean isNotAuthorizationHeader(HttpServletRequest request) {
return request.getHeader(AUTHORIZATION) == null;
}

private boolean isNotTokenParameter(HttpServletRequest request) {
return request.getParameter(AUTHORIZATION) == null;
}

}
14 changes: 9 additions & 5 deletions src/main/java/com/chat/yourway/security/JwtService.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,20 @@ public String generateRefreshToken(UserDetails userDetails) {
}

public String extractToken(HttpServletRequest request) {
final String authHeader = request.getHeader(AUTHORIZATION);
String token = request.getHeader(AUTHORIZATION);
if (token == null) {
token = request.getParameter(AUTHORIZATION);
}

final String tokenType = jwtProperties.getTokenType();
final String tokenTypePrefix = tokenType + " ";

if (isNotValidTokenType(authHeader, tokenTypePrefix)) {
if (isNotValidTokenType(token, tokenTypePrefix)) {
log.warn("Invalid token type, token type should be [{}]", tokenType);
throw new InvalidTokenException(
"Invalid token type, token type should be [" + tokenType + "]");
}
return authHeader.substring(tokenTypePrefix.length());
return token.substring(tokenTypePrefix.length());
}

public boolean isTokenValid(String token, UserDetails userDetails) {
Expand All @@ -67,8 +71,8 @@ private String generateAccessToken(Map<String, Object> extraClaims, UserDetails
return buildToken(extraClaims, userDetails, jwtProperties.getExpiration());
}

private boolean isNotValidTokenType(String authHeader, String tokenTypePrefix) {
return authHeader == null || !authHeader.startsWith(tokenTypePrefix);
private boolean isNotValidTokenType(String token, String tokenTypePrefix) {
return token == null || !token.startsWith(tokenTypePrefix);
}

private String buildToken(Map<String, Object> extraClaims, UserDetails userDetails,
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ security.jwt.expiration=3600000
security.jwt.refresh-expiration=604800000

#CORS:
cors.allowed-origins=${CORS_ORIGINS:http://localhost:8080}
cors.allowed-origins=${CORS_ORIGINS:http://localhost:8080,http://localhost:3000}
cors.allowed-methods=GET, POST, PUT, PATCH, DELETE
cors.allowed-headers=*
cors.allow-credentials=true

# SMTP Configuration
spring.mail.host=smtp.office365.com
spring.mail.host=${SMTP_HOST:smtp.gmail.com}
spring.mail.port=587
spring.mail.username=${EMAIL_ADDRESS:}
spring.mail.password=${EMAIL_PASSWORD:}
Expand Down
74 changes: 48 additions & 26 deletions src/main/resources/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,56 @@
<h1>WebSocket Chat Test Client</h1>

<p style="font-style: italic">
Get topic notification [/user/specific/notify/{id}]
Connect to WebSocket [http://localhost/chat?Authorization=Bearer {jwt_token}]
</p>
<div>
<label for="getTopicNotification">
<input type="number" id="getTopicNotification" placeholder="Enter topic id">
<label for="jwtToken">
<input type="text" id="jwtToken" placeholder="Enter JWT Token">
</label>

<button onclick="subscribeToNotificationFromTopic(document.getElementById('getTopicNotification').value)">Get notification</button>
<button onclick="initializeWebSocket()">Connect</button>
</div>
<br/>

<div id="notification"></div>
<br/>

<p style="font-style: italic">
Subscribe to topic [/topic/{id}]
</p>
<div>

<label for="subscribeToTopic">
<input type="number" id="subscribeToTopic" placeholder="Enter topic id">
</label>

<button onclick="subscribeToTopic()">Subscribe</button>
</div>

<p style="font-style: italic">
Get topic notification [/user/specific/notify/{id}]
</p>
<div>
<label for="getTopicNotification">
<input type="number" id="getTopicNotification" placeholder="Enter topic id">
</label>

<button
onclick="subscribeToNotificationFromTopic(document.getElementById('getTopicNotification').value)">
Get notification
</button>
</div>
<br/>

<div id="notification"></div>
<br/>

<p style="font-style: italic">
Get message history [/app/history/topic/{id}]
</p>
<div>
<label for="page">
<input type="number" id="page" placeholder="Enter page">
</label>
<label for="pageSize">
<input type="number" id="pageSize" placeholder="Enter pageSize">
</label>
<div>
<label for="page">
<input type="number" id="page" placeholder="Enter page">
</label>
<label for="pageSize">
<input type="number" id="pageSize" placeholder="Enter pageSize">
</label>

<button onclick="getHistoryTopic()">GetMessageHistory</button>
</div>
Expand Down Expand Up @@ -83,22 +98,29 @@ <h1>WebSocket Chat Test Client</h1>
</div>

<script>
const socket = new SockJS('/chat');
const stompClient = Stomp.over(socket);
const subToTopicDest = '/topic/';
const subToError = '/user/specific/error';
const subToNotificationDest = '/user/specific/notify/';
const sendToPublicTopicDest = "/app/topic/public/";
const sendToPrivateTopicDest = "/app/topic/private/";
const getHistoryTopicDest = "/app/history/topic/";
const tokenType = 'Bearer';
let socket = null;
let stompClient = null;

function initializeWebSocket() {
const jwtToken = document.getElementById('jwtToken').value;
socket = new SockJS('/chat?Authorization=' + tokenType + ' ' + jwtToken);
stompClient = Stomp.over(socket);

stompClient.connect({}, function (frame) {
console.log('Connected: ' + frame);
stompClient.connect({}, function (frame) {
console.log('Connected: ' + frame);

subscribeToError();
});
subscribeToError();
});
}

function subscribeToMessageHistory(){
function subscribeToMessageHistory() {
let topicId = document.getElementById('subscribeToTopic').value;

stompClient.subscribe('/user' + subToTopicDest + topicId, function (messages) {
Expand All @@ -116,10 +138,10 @@ <h1>WebSocket Chat Test Client</h1>

subscribeToMessageHistory();

stompClient.subscribe(subToTopicDest + topicId, function (messages) {
let parseMessage = JSON.parse(messages.body);
showMessage(parseMessage);
});
stompClient.subscribe(subToTopicDest + topicId, function (messages) {
let parseMessage = JSON.parse(messages.body);
showMessage(parseMessage);
});
}

function showMessage(message) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,9 @@ public class ChatControllerTest {
void setUp() {
String accessToken = getAccessToken();

String URL = "ws://localhost:" + port + "/chat";
String URL = "ws://localhost:" + port + "/chat?Authorization=" + "Bearer " + accessToken;

WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
headers.add("Authorization", "Bearer " + accessToken);

session = createWebSocketSession(URL, headers);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package com.chat.yourway.integration.service.impl;

import static com.github.springtestdbunit.annotation.DatabaseOperation.CLEAN_INSERT;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertThrows;

import com.chat.yourway.exception.MessageHasAlreadyReportedException;
import com.chat.yourway.integration.extension.PostgresExtension;
import com.chat.yourway.integration.extension.RedisExtension;
import com.chat.yourway.repository.ContactRepository;
import com.chat.yourway.repository.MessageRepository;
import com.chat.yourway.service.MessageServiceImpl;
import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseOperation;
import com.github.springtestdbunit.annotation.DatabaseSetup;
import com.github.springtestdbunit.annotation.DatabaseTearDown;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand All @@ -22,10 +25,6 @@
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertThrows;

@ExtendWith({PostgresExtension.class, RedisExtension.class})
@SpringBootTest
@TestExecutionListeners(
Expand All @@ -37,21 +36,23 @@
MockitoTestExecutionListener.class,
ResetMocksTestExecutionListener.class
})
@DatabaseSetup(value = {
"/dataset/mockdb/topic.xml",
"/dataset/mockdb/message.xml",
"/dataset/mockdb/contact.xml",
"/dataset/mockdb/contact_message_report.xml"},
type = CLEAN_INSERT)
public class MessageServiceImplTest {
@Autowired ContactRepository contactRepository;
@Autowired MessageRepository messageRepository;
@Autowired MessageServiceImpl messageService;

@Test
@DisplayName("should save report to message when user makes report")
@DatabaseSetup(value = "/dataset/report-to-message-dataset.xml", type = DatabaseOperation.INSERT)
@DatabaseTearDown(
value = "/dataset/report-to-message-dataset.xml",
type = DatabaseOperation.DELETE)
public void shouldSaveReportToMessage_WhenUserMakesReport() {
// Given
var messageId = 2;
var email = "user3@gmail.com";
var messageId = 101;
var email = "oleg@gmail.com";

// When
messageService.reportMessageById(messageId, email);
Expand All @@ -67,14 +68,10 @@ public void shouldSaveReportToMessage_WhenUserMakesReport() {

@Test
@DisplayName("should delete message when user makes report and message reached max attempts")
@DatabaseSetup(value = "/dataset/report-to-message-dataset.xml", type = DatabaseOperation.CLEAN_INSERT)
@DatabaseTearDown(
value = "/dataset/report-to-message-dataset.xml",
type = DatabaseOperation.DELETE)
public void shouldDeleteMessage_WhenUserMakesReportAndMessageReachedMaxAttempts() {
// Given
var messageId = 1;
var email = "user3@gmail.com";
var messageId = 100;
var email = "oleg@gmail.com";

// When
messageService.reportMessageById(messageId, email);
Expand All @@ -88,14 +85,10 @@ public void shouldDeleteMessage_WhenUserMakesReportAndMessageReachedMaxAttempts(

@Test
@DisplayName("should throw MessageHasAlreadyReportedException when user makes report again")
@DatabaseSetup(value = "/dataset/report-to-message-dataset.xml", type = DatabaseOperation.INSERT)
@DatabaseTearDown(
value = "/dataset/report-to-message-dataset.xml",
type = DatabaseOperation.DELETE)
public void shouldThrowMessageHasAlreadyReportedException_WhenUserMakesReportAgain() {
// Given
var messageId = 1;
var email = "user2@gmail.com";
var messageId = 100;
var email = "anton@gmail.com";

// When
// Then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class TopicSubscriberServiceImplTest {
@Test
@DatabaseSetup(
value = "/dataset/favourite-topics-of-contact.xml",
type = DatabaseOperation.INSERT)
type = DatabaseOperation.CLEAN_INSERT)
@DatabaseTearDown(
value = "/dataset/favourite-topics-of-contact.xml",
type = DatabaseOperation.DELETE)
Expand All @@ -73,7 +73,7 @@ public void shouldSuccessfullyAddTopicToFavourite_whenUserMarkTopicAsFavourite()
@Test
@DatabaseSetup(
value = "/dataset/favourite-topics-of-contact.xml",
type = DatabaseOperation.INSERT)
type = DatabaseOperation.CLEAN_INSERT)
@DatabaseTearDown(
value = "/dataset/favourite-topics-of-contact.xml",
type = DatabaseOperation.DELETE)
Expand All @@ -99,7 +99,7 @@ public void shouldSuccessfullyRemoveTopicFromFavourite_whenUserUnmarkTopicAsFavo
@Test
@DatabaseSetup(
value = "/dataset/favourite-topics-of-contact.xml",
type = DatabaseOperation.INSERT)
type = DatabaseOperation.CLEAN_INSERT)
@DatabaseTearDown(
value = "/dataset/favourite-topics-of-contact.xml",
type = DatabaseOperation.DELETE)
Expand All @@ -121,7 +121,7 @@ public void shouldThrowTopicNotFoundException_whenUserMarkTopicAsFavouriteAndTop
@Test
@DatabaseSetup(
value = "/dataset/favourite-topics-of-contact.xml",
type = DatabaseOperation.INSERT)
type = DatabaseOperation.CLEAN_INSERT)
@DatabaseTearDown(
value = "/dataset/favourite-topics-of-contact.xml",
type = DatabaseOperation.DELETE)
Expand All @@ -144,7 +144,7 @@ public void shouldThrowTopicNotFoundException_whenUserMarkTopicAsFavouriteAndTop
@Test
@DatabaseSetup(
value = "/dataset/favourite-topics-of-contact.xml",
type = DatabaseOperation.INSERT)
type = DatabaseOperation.CLEAN_INSERT)
@DatabaseTearDown(
value = "/dataset/favourite-topics-of-contact.xml",
type = DatabaseOperation.DELETE)
Expand All @@ -167,7 +167,7 @@ public void shouldThrowTopicNotFoundException_whenUserMarkTopicAsFavouriteAndTop
@Test
@DatabaseSetup(
value = "/dataset/favourite-topics-of-contact.xml",
type = DatabaseOperation.INSERT)
type = DatabaseOperation.CLEAN_INSERT)
@DatabaseTearDown(
value = "/dataset/favourite-topics-of-contact.xml",
type = DatabaseOperation.DELETE)
Expand All @@ -190,7 +190,7 @@ public void shouldThrowTopicNotFoundException_whenUserMarkTopicAsFavouriteAndTop
@Test
@DatabaseSetup(
value = "/dataset/complain-topic-dataset.xml",
type = DatabaseOperation.INSERT)
type = DatabaseOperation.CLEAN_INSERT)
@DatabaseTearDown(
value = "/dataset/complain-topic-dataset.xml",
type = DatabaseOperation.DELETE)
Expand Down Expand Up @@ -218,7 +218,7 @@ public void shouldSuccessfullyComplainTopic_whenUserComplainTopic() {
@Test
@DatabaseSetup(
value = "/dataset/complain-topic-dataset.xml",
type = DatabaseOperation.INSERT)
type = DatabaseOperation.CLEAN_INSERT)
@DatabaseTearDown(
value = "/dataset/complain-topic-dataset.xml",
type = DatabaseOperation.DELETE)
Expand All @@ -240,7 +240,7 @@ public void shouldThrowTopicNotFoundException_whenUserComplainTopic() {
@Test
@DatabaseSetup(
value = "/dataset/complain-topic-dataset.xml",
type = DatabaseOperation.INSERT)
type = DatabaseOperation.CLEAN_INSERT)
@DatabaseTearDown(
value = "/dataset/complain-topic-dataset.xml",
type = DatabaseOperation.DELETE)
Expand Down
Loading
Loading