Skip to content

Commit

Permalink
feat():add search messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Thibaut-Mouton committed Jun 18, 2024
1 parent c81b5df commit bd333f3
Show file tree
Hide file tree
Showing 32 changed files with 579 additions and 406 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ Real time chat application group oriented built with React and Spring Boot. Talk
* [Material UI](https://mui.com/) v5.7.0
* [MySQL Server](https://www.mysql.com/)

# What's next ?
You want to know the roadmap of the project, next release or next fixes ? Check the "Projects" tab or visit the [Fast Lite Message's roadmap](https://github.com/users/Thibaut-Mouton/projects/4)

# Project fast start up
In a hurry ? Juste type ```docker-compose up``` in the root directory.
This will start 3 containers : MySQL, backend and frontend together. Liquibase will take care of the database setup. For development purpose, the DB is filled with 5 accounts (password: ```root```) :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.requestMatchers("/messenger", "/websocket", "/ws").permitAll()
.requestMatchers("/csrf").permitAll()
.requestMatchers("/auth").permitAll()
.requestMatchers("/user/register").permitAll()
.requestMatchers("/health-check").permitAll()
.anyRequest().authenticated())
.logout(AbstractHttpConfigurer::disable)
Expand Down
15 changes: 8 additions & 7 deletions backend/src/main/java/com/mercure/controller/ApiController.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.mercure.service.GroupService;
import com.mercure.service.GroupUserJoinService;
import com.mercure.service.UserService;
import com.mercure.utils.ColorsUtils;
import com.mercure.utils.JwtUtil;
import com.mercure.utils.StaticVariable;
import jakarta.servlet.http.Cookie;
Expand Down Expand Up @@ -171,17 +172,17 @@ public ResponseEntity<?> createUser(@RequestBody String data) {
Gson gson = new Gson();
AuthenticationUserDTO userDTO = gson.fromJson(data, AuthenticationUserDTO.class);

// Check if there are matched in DB
if ((userService.checkIfUserNameOrMailAlreadyUsed(userDTO.getFirstName(), userDTO.getEmail()))) {
return ResponseEntity.badRequest().body("Username or mail already used, please try again");
if ((userService.checkIfUserNameOrMailAlreadyUsed(userDTO.getEmail()))) {
return ResponseEntity.badRequest().body("mail already used, please choose another");
}
UserEntity user = new UserEntity();
user.setFirstName(userDTO.getFirstName());
user.setLastName(userDTO.getLastName());
user.setFirstName(userDTO.getFirstname());
user.setLastName(userDTO.getLastname());
user.setMail(userDTO.getEmail());
user.setPassword(userService.passwordEncoder(userDTO.getPassword()));
user.setShortUrl(userService.createShortUrl(userDTO.getFirstName(), userDTO.getLastName()));
user.setShortUrl(userService.createShortUrl(userDTO.getFirstname(), userDTO.getLastname()));
user.setWsToken(UUID.randomUUID().toString());
user.setColor(new ColorsUtils().getRandomColor());
user.setRole(1);
user.setAccountNonExpired(true);
user.setAccountNonLocked(true);
Expand All @@ -190,7 +191,7 @@ public ResponseEntity<?> createUser(@RequestBody String data) {
try {
userService.save(user);
log.info("User saved successfully");
return ResponseEntity.ok().build();
return ResponseEntity.ok().body("User saved successfully");
} catch (Exception e) {
log.error("Error while registering user : {}", e.getMessage());
}
Expand Down
17 changes: 6 additions & 11 deletions backend/src/main/java/com/mercure/controller/SearchController.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package com.mercure.controller;

import com.mercure.dto.search.FullTextSearchDTO;
import com.mercure.entity.GroupUser;
import com.mercure.dto.search.FullTextSearchResponseDTO;
import com.mercure.entity.UserEntity;
import com.mercure.service.GroupUserJoinService;
import com.mercure.service.MessageService;
import com.mercure.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

import java.util.List;

Expand All @@ -23,14 +20,12 @@ public class SearchController {
private UserService userService;

@Autowired
private GroupUserJoinService groupUserJoinService;
private MessageService messageService;

@PostMapping()
public void searchInDiscussions(FullTextSearchDTO search, Authentication authentication) {
public FullTextSearchResponseDTO searchInDiscussions(@RequestBody FullTextSearchDTO search, Authentication authentication) {
String name = authentication.getName();
UserEntity user = this.userService.findByNameOrEmail(name, name);
List<Integer> groupUser = groupUserJoinService.findAllGroupsByUserId(user.getId());
groupUser.forEach(groupUserJoin -> {
});
return this.messageService.searchMessages(user.getId(), search.getText());
}
}
2 changes: 2 additions & 0 deletions backend/src/main/java/com/mercure/dto/AuthUserDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,7 @@ public class AuthUserDTO {

private String wsToken;

private String color;

private List<GroupDTO> groups;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
@NoArgsConstructor
public class AuthenticationUserDTO {

private String firstName;
private String firstname;

private String lastName;
private String lastname;

private String password;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.mercure.dto.search;

public interface FullTextSearchDatabaseResponse {
int getId();

String getGroupUrl();

String getMessage();

String getGroupName();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.mercure.dto.search;

import lombok.*;

import java.util.List;

@Data
public class FullTextSearchDatabaseResponseDTO {

private Integer id;

private String groupUrl;

private List<String> messages;

private String groupName;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.mercure.dto.search;

import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Getter
@Setter
public class FullTextSearchResponseDTO {

private String matchingText;

private List<FullTextSearchDatabaseResponseDTO> matchingMessages;
}
3 changes: 2 additions & 1 deletion backend/src/main/java/com/mercure/dto/user/InitUserDTO.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mercure.dto.user;

import com.mercure.dto.AuthUserDTO;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -13,7 +14,7 @@
@AllArgsConstructor
public class InitUserDTO {

private UserDTO user;
private AuthUserDTO user;

private List<GroupWrapperDTO> groupsWrapper;
}
27 changes: 0 additions & 27 deletions backend/src/main/java/com/mercure/dto/user/UserDTO.java

This file was deleted.

10 changes: 4 additions & 6 deletions backend/src/main/java/com/mercure/mapper/UserMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.mercure.dto.user.GroupDTO;
import com.mercure.dto.user.GroupWrapperDTO;
import com.mercure.dto.user.InitUserDTO;
import com.mercure.dto.user.UserDTO;
import com.mercure.entity.GroupEntity;
import com.mercure.entity.UserEntity;
import com.mercure.utils.ComparatorListGroupDTO;
Expand All @@ -31,18 +30,18 @@ public class UserMapper {
* The password is not sent
*
* @param userEntity the {@link UserEntity} to map
* @return a {@link UserDTO}
* @return a {@link AuthUserDTO}
*/
public InitUserDTO toUserDTO(UserEntity userEntity) {
UserDTO userDTO = new UserDTO();
AuthUserDTO userDTO = new AuthUserDTO();
InitUserDTO initUserDTO = new InitUserDTO();
List<GroupWrapperDTO> groupWrapperDTOS = new ArrayList<>();

userDTO.setId(userEntity.getId());
userDTO.setFirstName(userEntity.getFirstName());
userDTO.setLastName(userEntity.getLastName());
userDTO.setWsToken(userEntity.getWsToken());
userDTO.setJwt(userEntity.getJwt());
userDTO.setColor(userEntity.getColor());

userEntity.getGroupSet().forEach(groupEntity -> {
GroupWrapperDTO groupWrapperDTO = new GroupWrapperDTO();
Expand All @@ -62,14 +61,13 @@ public InitUserDTO toUserDTO(UserEntity userEntity) {
return initUserDTO;
}


public AuthUserDTO toLightUserDTO(UserEntity userEntity) {
Set<GroupEntity> groups = userEntity.getGroupSet();
List<GroupDTO> allUserGroups = new ArrayList<>(userEntity.getGroupSet().stream()
.map((groupEntity) -> groupMapper.toGroupDTO(groupEntity, userEntity.getId())).toList());
Optional<GroupEntity> groupUrl = groups.stream().findFirst();
String lastGroupUrl = groupUrl.isPresent() ? groupUrl.get().getUrl() : "";
allUserGroups.sort(new ComparatorListGroupDTO());
return new AuthUserDTO(userEntity.getId(), userEntity.getFirstName(), userEntity.getLastName(), lastGroupUrl, userEntity.getWsToken(), allUserGroups);
return new AuthUserDTO(userEntity.getId(), userEntity.getFirstName(), userEntity.getLastName(), lastGroupUrl, userEntity.getWsToken(), userEntity.getColor(), allUserGroups);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mercure.repository;

import com.mercure.dto.search.FullTextSearchDatabaseResponse;
import com.mercure.entity.MessageEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
Expand All @@ -24,8 +25,8 @@ public interface MessageRepository extends JpaRepository<MessageEntity, Integer>
@Query(value = "SELECT m1.id FROM message m1 INNER JOIN (SELECT MAX(m.id) as id FROM message m GROUP BY m.msg_group_id) temp ON temp.id = m1.id WHERE msg_group_id = :idOfGroup", nativeQuery = true)
int findLastMessageIdByGroupId(@Param(value = "idOfGroup") int groupId);

@Query(value = "SELECT m. FROM message m WHERE m.id = :idOfGroup AND m.type = 'FILE'", nativeQuery = true)
List<MessageEntity> findAllFilesByGroupId(@Param(value = "idOfGroup") int groupId);
@Query(value = "SELECT m.message as message, c.id, c.url as groupUrl, c.name as groupName FROM message m LEFT JOIN chat_group c ON c.id = m.msg_group_id WHERE m.msg_group_id IN :groupIds AND m.message LIKE %:searchQuery%", nativeQuery = true)
List<FullTextSearchDatabaseResponse> findMessagesBySearchQuery(@Param(value = "searchQuery") String searchQuery, @Param(value = "groupIds") List<Integer> groupIds);

@Modifying
@Query(value = "DELETE m, mu FROM message m JOIN message_user mu ON m.id = mu.message_id WHERE m.msg_group_id = :groupId", nativeQuery = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public interface UserRepository extends JpaRepository<UserEntity, Integer> {
@Query(value = "SELECT * FROM users u WHERE u.id NOT IN :ids", nativeQuery = true)
List<UserEntity> getAllUsersNotAlreadyInConversation(@Param(value = "ids") int[] ids);

int countAllByFirstNameOrMail(String firstName, String mail);
int countAllByMail(String mail);

int countAllByShortUrl(String shortUrl);
}
30 changes: 30 additions & 0 deletions backend/src/main/java/com/mercure/service/MessageService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import com.mercure.dto.MessageDTO;
import com.mercure.dto.NotificationDTO;
import com.mercure.dto.WrapperMessageDTO;
import com.mercure.dto.search.FullTextSearchDatabaseResponse;
import com.mercure.dto.search.FullTextSearchDatabaseResponseDTO;
import com.mercure.dto.search.FullTextSearchResponseDTO;
import com.mercure.entity.*;
import com.mercure.repository.MessageRepository;
import com.mercure.utils.MessageTypeEnum;
Expand All @@ -12,6 +15,7 @@
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class MessageService {
Expand All @@ -31,6 +35,9 @@ public class MessageService {
@Autowired
private UserService userService;

@Autowired
private GroupUserJoinService groupUserJoinService;

public MessageEntity createAndSaveMessage(int userId, int groupId, String type, String data) {
MessageEntity msg = new MessageEntity(userId, groupId, type, data);
return messageRepository.save(msg);
Expand Down Expand Up @@ -161,6 +168,29 @@ public List<String> getMultimediaContentByGroup(String groupUrl) {
return fileService.getFilesUrlByGroupId(groupId);
}

public FullTextSearchResponseDTO searchMessages(int userId, String searchText) {
List<Integer> groupIds = groupUserJoinService.findAllGroupsByUserId(userId);
List<FullTextSearchDatabaseResponse> responseFromDB = messageRepository.findMessagesBySearchQuery(searchText, groupIds);
FullTextSearchResponseDTO result = new FullTextSearchResponseDTO();
Map<Integer, List<FullTextSearchDatabaseResponse>> studlistGrouped =
responseFromDB.stream().collect(Collectors.groupingBy(FullTextSearchDatabaseResponse::getId));
result.setMatchingText(searchText);
List<FullTextSearchDatabaseResponseDTO> matchingMessages = new ArrayList<>();
for (Map.Entry<Integer, List<FullTextSearchDatabaseResponse>> entry : studlistGrouped.entrySet()) {
if (entry.getValue().get(0) != null) {
FullTextSearchDatabaseResponseDTO fullTextSearchDTO = new FullTextSearchDatabaseResponseDTO();
List<String> messages = entry.getValue().stream().map(FullTextSearchDatabaseResponse::getMessage).toList();
fullTextSearchDTO.setMessages(messages);
fullTextSearchDTO.setId(entry.getKey());
fullTextSearchDTO.setGroupUrl(entry.getValue().get(0).getGroupUrl());
fullTextSearchDTO.setGroupName(entry.getValue().get(0).getGroupName());
matchingMessages.add(fullTextSearchDTO);
}
}
result.setMatchingMessages(matchingMessages);
return result;
}

public WrapperMessageDTO getConversationMessage(String url, int messageId) {
WrapperMessageDTO wrapper = new WrapperMessageDTO();
if (url != null) {
Expand Down
6 changes: 2 additions & 4 deletions backend/src/main/java/com/mercure/service/UserService.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.mercure.service;

import com.mercure.dto.GroupMemberDTO;
import com.mercure.dto.user.InitUserDTO;
import com.mercure.dto.user.UserDTO;
import com.mercure.entity.GroupRoleKey;
import com.mercure.entity.GroupUser;
import com.mercure.entity.UserEntity;
Expand Down Expand Up @@ -120,7 +118,7 @@ public String passwordEncoder(String str) {
return passwordEncoder.encode(str);
}

public boolean checkIfUserNameOrMailAlreadyUsed(String firstName, String mail) {
return userRepository.countAllByFirstNameOrMail(firstName, mail) > 0;
public boolean checkIfUserNameOrMailAlreadyUsed(String mail) {
return userRepository.countAllByMail(mail) > 0;
}
}
5 changes: 3 additions & 2 deletions frontend-web/src/components/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const HomeComponent = (): React.JSX.Element => {

return (
<div className={generateColorMode(theme)} style={{height: "100%", display: "flex", alignItems: "center"}}>
<Grid sx={{m: 2}} container xs={12}>
<Grid sx={{m: 2}} container>
<Card variant="outlined">
<CardContent>
<Typography variant="h5" gutterBottom>
Expand All @@ -28,7 +28,8 @@ export const HomeComponent = (): React.JSX.Element => {
<Box display={"flex"} flexDirection={"column"}>
<img src={"/assets/icons/landing_logo.svg"} height={"150"} alt={"test svg"}/>
<Box>
FastLiteMessage allows to communicate with other people everywhere, create groups, make
FastLiteMessage allows to communicate with other people everywhere, create groups,
make
serverless video calls in an easy way. Log into your account or register to start
using FastLiteMessage.
</Box>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.simple-highlight {
background-color: rgba(255, 184, 0, 0.62);
padding: 0.1em 0.2em;
}
Loading

0 comments on commit bd333f3

Please sign in to comment.