Implemented primitive rest validation.
A better implementation to be done later.
This commit is contained in:
parent
97091123b9
commit
d3ac95e8f4
@ -7,6 +7,8 @@ import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.ros.chatto.dto.ChatMessageDTO;
|
||||
import org.ros.chatto.dto.ReencryptionDTO;
|
||||
import org.ros.chatto.model.ChatMessage;
|
||||
@ -34,7 +36,7 @@ public class AdminRESTController {
|
||||
|
||||
@PostMapping(value = "/post/re-encrypt", consumes = { "application/json" })
|
||||
@ResponseBody
|
||||
public ResponseEntity<ReencryptionDTO> reencryptMessages(@RequestBody List<ReencryptionDTO> reencryptionDTOs,
|
||||
public ResponseEntity<ReencryptionDTO> reencryptMessages(@RequestBody @Valid List<ReencryptionDTO> reencryptionDTOs,
|
||||
Principal principal) {
|
||||
if (reencryptionDTOs.size() > 0) {
|
||||
chatService.reencryptMessages(reencryptionDTOs);
|
||||
|
@ -6,16 +6,23 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.ros.chatto.dto.ChatMessageDTO;
|
||||
import org.ros.chatto.dto.MessageCipherDTO;
|
||||
import org.ros.chatto.dto.ReencryptionDTO;
|
||||
import org.ros.chatto.model.MessageCipher;
|
||||
import org.ros.chatto.error.ErrorModel;
|
||||
import org.ros.chatto.error.ErrorResponse;
|
||||
import org.ros.chatto.service.ChatService;
|
||||
import org.ros.chatto.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -23,6 +30,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@ -36,14 +44,52 @@ public class ChatMessageController {
|
||||
|
||||
@PostMapping(value = "/post/message", consumes = { "application/json" })
|
||||
@ResponseBody
|
||||
public ResponseEntity<ChatMessageDTO> newMessage(@RequestBody ChatMessageDTO chatMessageDTO, Principal principal) {
|
||||
public ResponseEntity<?> newMessage(@RequestBody @Valid ChatMessageDTO chatMessageDTO,
|
||||
Principal principal) {
|
||||
// if (bindingResult.hasErrors()) {
|
||||
//
|
||||
//// return new ResponseEntity<List<FieldError>>(bindingResult.getFieldErrors(),HttpStatus.BAD_REQUEST);
|
||||
// return new ResponseEntity<ErrorResponse>(handleException(bindingResult), HttpStatus.BAD_REQUEST);
|
||||
// }
|
||||
MessageCipherDTO messageCipher = chatMessageDTO.getMessageCipher();
|
||||
String fromUser = principal.getName();
|
||||
String toUser = chatMessageDTO.getToUser();
|
||||
System.out.println("Message cipher = " + messageCipher);
|
||||
chatService.saveNewMessage(fromUser, toUser, messageCipher);
|
||||
return new ResponseEntity<ChatMessageDTO>(HttpStatus.OK);
|
||||
chatMessageDTO = chatService.saveNewMessage(fromUser, toUser, messageCipher);
|
||||
HttpHeaders responseHeader = new HttpHeaders();
|
||||
return new ResponseEntity<ChatMessageDTO>(chatMessageDTO, responseHeader, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that check against {@code @Valid} Objects passed to controller endpoints
|
||||
*
|
||||
* @param exception
|
||||
* @return a {@code ErrorResponse}
|
||||
* @see com.aroussi.util.validation.ErrorResponse
|
||||
*/
|
||||
@ExceptionHandler(value=MethodArgumentNotValidException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public ErrorResponse handleException(MethodArgumentNotValidException exception) {
|
||||
|
||||
List<ErrorModel> errorMessages = exception.getBindingResult().getFieldErrors().stream()
|
||||
.map(err -> new ErrorModel(err.getField(), err.getRejectedValue(), err.getDefaultMessage()))
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
return ErrorResponse.builder().errorMessage(errorMessages).build();
|
||||
}
|
||||
|
||||
@ExceptionHandler(value=MethodArgumentNotValidException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public ErrorResponse handleException(BindingResult bindingResult) {
|
||||
|
||||
List<ErrorModel> errorMessages = bindingResult.getFieldErrors().stream()
|
||||
.map(err -> new ErrorModel(err.getField(), err.getRejectedValue(), err.getDefaultMessage()))
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
return ErrorResponse.builder().errorMessage(errorMessages).build();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@GetMapping(value = "/get/messages/{userName}")
|
||||
@ResponseBody
|
||||
|
@ -25,8 +25,9 @@ public class RegistrationController {
|
||||
}
|
||||
|
||||
@PostMapping("/perform_registration")
|
||||
public String performRegistration(Model model,
|
||||
@ModelAttribute("userRegistrationDTO") @Valid UserRegistrationDTO userRegistrationDTO, BindingResult bindingResult) {
|
||||
public String performRegistration(
|
||||
@ModelAttribute("userRegistrationDTO") @Valid UserRegistrationDTO userRegistrationDTO,
|
||||
BindingResult bindingResult) {
|
||||
if (bindingResult.hasErrors()) {
|
||||
System.out.println("Input has errors!");
|
||||
return "registration";
|
@ -2,13 +2,21 @@ package org.ros.chatto.dto;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.ros.chatto.model.MessageCipher;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ChatMessageDTO {
|
||||
private String toUser, fromUser;
|
||||
@NotBlank(message = "Username should not be blank")
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "Username must be alphanumeric")
|
||||
@Size(max=15)
|
||||
private String toUser;
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "Username must be alphanumeric")
|
||||
@Size(max=15)
|
||||
private String fromUser;
|
||||
private MessageCipherDTO messageCipher;
|
||||
private Date messageTime;
|
||||
}
|
||||
|
@ -1,5 +1,11 @@
|
||||
package org.ros.chatto.dto;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import lombok.Getter;
|
||||
@ -8,18 +14,39 @@ import lombok.Setter;
|
||||
@Getter
|
||||
@Setter
|
||||
public class MessageCipherDTO {
|
||||
@Pattern(regexp = "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$") // regex for base64
|
||||
@NotBlank
|
||||
private String iv;
|
||||
@Max(1)
|
||||
@NotBlank
|
||||
private int v;
|
||||
@Max(1_000_000)
|
||||
@Min(1_000)
|
||||
@NotBlank
|
||||
@JsonProperty("iter")
|
||||
private int iterations;
|
||||
@Max(256)
|
||||
@Min(128)
|
||||
@JsonProperty("ks")
|
||||
private int keySize;
|
||||
@Max(256)
|
||||
@Min(128)
|
||||
@JsonProperty("ts")
|
||||
private int tagSize;
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$") // alphabetic
|
||||
@NotBlank
|
||||
private String mode;
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$")
|
||||
private String adata;
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$")
|
||||
@NotBlank
|
||||
private String cipher;
|
||||
@Pattern(regexp = "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")
|
||||
@NotBlank
|
||||
private String salt;
|
||||
@JsonProperty("ct")
|
||||
@Pattern(regexp = "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")
|
||||
@NotBlank
|
||||
@Size(max = 2000, min = 1)
|
||||
private String cipherText;
|
||||
}
|
||||
|
@ -2,13 +2,22 @@ package org.ros.chatto.dto;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.ros.chatto.model.MessageCipher;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ReencryptionDTO {
|
||||
@NotBlank(message = "Username should not be blank")
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "Username must be alphanumeric")
|
||||
@Size(max=15)
|
||||
private String toUser, fromUser;
|
||||
@NotBlank
|
||||
@Size(max=600)
|
||||
private MessageCipher messageCipher;
|
||||
private Date messageTime;
|
||||
}
|
||||
|
@ -7,13 +7,13 @@ import javax.validation.constraints.Size;
|
||||
|
||||
public class UserRegistrationDTO {
|
||||
@Size(min = 4, max = 10, message = "Username must be between 4 and 10 characters")
|
||||
@NotBlank(message = " Username should not be blank")
|
||||
@NotBlank(message = "Username should not be blank")
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "Username must be alphanumeric")
|
||||
private String userName;
|
||||
@Transient
|
||||
@Size(min = 4, max = 75, message = "Username must be between 4 and 75 characters")
|
||||
@NotBlank(message = " Password should not be blank")
|
||||
@Pattern(regexp = "^.*(?=.{6,})(?=.*d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$", message = "Invalid password format")
|
||||
@Size(min = 4, max = 75, message = "Password must be between 4 and 75 characters")
|
||||
@NotBlank(message = "Password should not be blank")
|
||||
// @Pattern(regexp = "^.*(?=.{6,})(?=.*d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$", message = "Invalid password format")
|
||||
private String password;
|
||||
|
||||
public String getUserName() {
|
||||
|
16
chatto/src/main/java/org/ros/chatto/error/ErrorModel.java
Normal file
16
chatto/src/main/java/org/ros/chatto/error/ErrorModel.java
Normal file
@ -0,0 +1,16 @@
|
||||
package org.ros.chatto.error;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ErrorModel{
|
||||
private String fieldName;
|
||||
private Object rejectedValue;
|
||||
private String messageError;
|
||||
|
||||
|
||||
}
|
17
chatto/src/main/java/org/ros/chatto/error/ErrorResponse.java
Normal file
17
chatto/src/main/java/org/ros/chatto/error/ErrorResponse.java
Normal file
@ -0,0 +1,17 @@
|
||||
package org.ros.chatto.error;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ErrorResponse {
|
||||
private List<ErrorModel> errorMessage;
|
||||
|
||||
}
|
@ -28,12 +28,12 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
@JsonIgnoreProperties(value = { "password"}, allowGetters = false)
|
||||
@JsonIgnoreProperties(value = { "password" }, allowGetters = false)
|
||||
|
||||
public class ChatUser {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
// @SequenceGenerator(name="user_generator", sequenceName = "user_seq", allocationSize=50)
|
||||
// @SequenceGenerator(name="user_generator", sequenceName = "user_seq", allocationSize=50) //mysql does not support sequence id generator
|
||||
@Column(name = "user_id")
|
||||
private int userID;
|
||||
@Column(name = "name")
|
||||
@ -47,7 +47,7 @@ public class ChatUser {
|
||||
@JsonBackReference
|
||||
// private Set<UserRole> userRoles = new HashSet<UserRole>();
|
||||
private Set<UserRole> userRoles;
|
||||
|
||||
|
||||
public int getUserID() {
|
||||
return userID;
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package org.ros.chatto.service;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.ros.chatto.dto.ChatMessageDTO;
|
||||
import org.ros.chatto.dto.MessageCipherDTO;
|
||||
import org.ros.chatto.dto.ReencryptionDTO;
|
||||
@ -10,7 +12,7 @@ import org.ros.chatto.model.ChatMessage;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
||||
public interface ChatService {
|
||||
public void saveNewMessage(String fromUser, String toUser, MessageCipherDTO messageCipherDTO);
|
||||
public @Valid ChatMessageDTO saveNewMessage(String fromUser, String toUser, MessageCipherDTO messageCipherDTO);
|
||||
|
||||
public List<ChatMessageDTO> getAllMessages(String fromUser, String toUser);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.ros.chatto.service;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@ -34,18 +35,26 @@ public class ChatServiceImpl implements ChatService {
|
||||
@Autowired
|
||||
MyConversionService myConversionService;
|
||||
|
||||
public void saveNewMessage(String fromUserName, String toUserName, MessageCipherDTO messageCipherDTO) {
|
||||
@Transactional
|
||||
public ChatMessageDTO saveNewMessage(String fromUserName, String toUserName, MessageCipherDTO messageCipherDTO) {
|
||||
|
||||
MessageCipher messageCipher = myConversionService.convertToMessageCipher(messageCipherDTO);
|
||||
ChatUser fromUser = userRepository.findByUserName(fromUserName);
|
||||
ChatUser toUser = userRepository.findByUserName(toUserName);
|
||||
|
||||
// if(fromUser ==null || toUser == null)
|
||||
// {
|
||||
// System.out.println("User is null");
|
||||
// throw new SQLException();
|
||||
// }
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
messageCipher = messageCipherRepository.save(messageCipher);
|
||||
chatMessage.setMessageCipher(messageCipher);
|
||||
chatMessage.setFromUser(fromUser);
|
||||
chatMessage.setToUser(toUser);
|
||||
|
||||
chatMessageRepository.save(chatMessage);
|
||||
chatMessage = chatMessageRepository.save(chatMessage);
|
||||
return myConversionService.convertToChatMessageDTO(chatMessage);
|
||||
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@ package org.ros.chatto.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
import org.ros.chatto.dto.UserRegistrationDTO;
|
||||
import org.ros.chatto.model.ChatUser;
|
||||
import org.ros.chatto.model.Role;
|
||||
@ -31,6 +33,7 @@ public class UserServiceImpl implements UserService{
|
||||
UserRepositoryCustom userRepositoryCustom;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void saveChatUser(ChatUser user) {
|
||||
// TODO Auto-generated method stub
|
||||
ChatUser changedUser = userRepository.save(user);
|
||||
@ -41,6 +44,7 @@ public class UserServiceImpl implements UserService{
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void registerUser(UserRegistrationDTO userRegistrationDTO) {
|
||||
// TODO Auto-generated method stub
|
||||
ChatUser user = new ChatUser();
|
||||
|
@ -62,7 +62,6 @@ function handleChangePassphraseForm() {
|
||||
messageCiphers.push(messageCipherNewObj);
|
||||
|
||||
// let messageCipherJson = JSON.stringify(messageCipherNewObj);
|
||||
let fromUser = sessionStorage.getItem('username');
|
||||
let chatMessageDTO = {
|
||||
"toUser": user,
|
||||
"fromUser": username,
|
||||
|
@ -16,11 +16,11 @@
|
||||
|
||||
<link th:href="@{/css/master.css}" href="../static/css/master.css" rel="stylesheet">
|
||||
<link th:href="@{/css/colors.css}" href="../static/css/colors.css" rel="stylesheet">
|
||||
</link>
|
||||
|
||||
<script th:inline="javascript">
|
||||
var hostAddress = window.location.host;
|
||||
/* var hostAddress2 = [[#{test.bindAddress}]]; */
|
||||
console.log("hostname" + window.location.host);
|
||||
// console.log("hostname" + window.location.host);
|
||||
</script>
|
||||
|
||||
<meta charset="UTF-8">
|
||||
|
@ -17,7 +17,7 @@
|
||||
<div class="row">
|
||||
<div class="col-sm py-5">
|
||||
<!-- <h4 class="display-4 text-center py-2">Chat</h4> -->
|
||||
<div class="card text-white bg-primary mb-3 text-center card-form rounded mx-auto" id="login-card">
|
||||
<div class="card text-white bg-primary mb-3 card-form rounded mx-auto" id="login-card">
|
||||
|
||||
<div class="card-body rounded">
|
||||
<!-- <h4 class="card-title">Chat</h4> -->
|
||||
@ -36,22 +36,19 @@
|
||||
</div> -->
|
||||
|
||||
<div class="card-text">
|
||||
<h2 class="card-title">Register</h2>
|
||||
<h2 class="card-title text-center">Register</h2>
|
||||
<form action="#" th:action="@{/perform_registration}" th:object=${userRegistrationDTO} method="POST">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Enter username: </label>
|
||||
<div th:classappend="${#fields.hasErrors('userName')} ? 'input-icon right' : ''">
|
||||
<i th:if="${#fields.hasErrors('userName')}" class="fa fa-exclamation tooltips" data-original-title="please enter a valid username" data-container="body"></i>
|
||||
<input class="form-control" th:field="*{userName}" type="text" name="username" id="username" required>
|
||||
<span th:if="${#fields.hasErrors('userName')}" class="help-block" th:errors="*{userName}"></span>
|
||||
</div>
|
||||
<input th:classappend="${#fields.hasErrors('userName')} ? 'is-invalid' : ''" class="form-control" th:field="*{userName}" type="text" name="username" required>
|
||||
<small class="form-text">Username must be alphanumeric</small>
|
||||
<span th:if="${#fields.hasErrors('userName')}" class="help-block text-danger" th:errors="*{userName}"></span>
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Enter password: </label>
|
||||
<i th:if="${#fields.hasErrors('password')}" class="fa fa-exclamation tooltips" data-original-title="please enter a valid first name" data-container="body"></i>
|
||||
<input class="form-control" th:field="*{password}" type="password" name="password" id="password" required>
|
||||
<span th:if="${#fields.hasErrors('password')}" class="help-block" th:errors="*{password}"></span>
|
||||
<input th:classappend="${#fields.hasErrors('password')} ? 'is-invalid' : ''" class="form-control" th:field="*{password}" type="password" name="password" id="password" required>
|
||||
<span th:if="${#fields.hasErrors('password')}" class="help-block text-danger" th:errors="*{password}"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password-repeat">Repeat password: </label>
|
||||
|
Loading…
Reference in New Issue
Block a user