From 3ea46b584a845a56db2681d0a9e577bc9a3bedbb Mon Sep 17 00:00:00 2001
From: Rohan Sircar
Date: Wed, 2 Oct 2019 21:55:46 +0530
Subject: [PATCH] zz
---
chatto/pom.xml | 14 +-
.../org/ros/chatto/BeanConfigurations.java | 20 +-
.../org/ros/chatto/ChattoApplication.java | 1 +
.../chatto/RestAuthenticationEntryPoint.java | 42 +++
.../main/java/org/ros/chatto/WebConfig.java | 20 ++
.../ros/chatto/WebSecurityConfiguration.java | 158 +++++++----
.../controller/ChatMessageController.java | 76 +++++
.../chatto/controller/DemoRestController.java | 60 +++-
.../java/org/ros/chatto/controller/Home.java | 46 ++-
.../chatto/controller/RegisterController.java | 8 +-
chatto/src/main/java/org/ros/chatto/datae.sql | 39 +++
.../org/ros/chatto/dto/ChatMessageDTO.java | 14 +
.../org/ros/chatto/dto/UserPublicDTO.java | 14 +
.../ros/chatto/dto/UserRegistrationDTO.java | 4 +-
.../org/ros/chatto/model/ChatMessage.java | 4 +-
.../main/java/org/ros/chatto/model/Role.java | 3 +-
.../repository/ChatMessageRepository.java | 19 +-
.../repository/UserRepositoryCustomImpl.java | 8 +-
.../src/main/java/org/ros/chatto/scheme.sql | 187 ++++++++++++
.../org/ros/chatto/service/ChatService.java | 17 ++
.../ros/chatto/service/ChatServiceImpl.java | 68 +++++
.../chatto/service/MyConversionService.java | 58 ++++
.../org/ros/chatto/service/UserService.java | 11 +-
.../ros/chatto/service/UserServiceImpl.java | 20 +-
.../src/main/resources/application.properties | 5 +-
.../src/main/resources/static/css/master.css | 24 ++
chatto/src/main/resources/static/js/chat.js | 267 ++++++++++++++++++
.../src/main/resources/static/js/loginPage.js | 19 ++
.../src/main/resources/static/js/my_Crypto.js | 57 ++++
chatto/src/main/resources/static/js/scljs.js | 60 ++++
chatto/src/main/resources/templates/chat.html | 39 +++
.../src/main/resources/templates/crypto.html | 18 ++
.../resources/templates/fragments/head.html | 23 ++
.../src/main/resources/templates/login.html | 45 ++-
.../resources/templates/registration.html | 1 +
.../main/resources/templates/restLogout.html | 12 +
.../ros/chatto/ChattoApplicationTests.java | 27 +-
37 files changed, 1380 insertions(+), 128 deletions(-)
create mode 100644 chatto/src/main/java/org/ros/chatto/RestAuthenticationEntryPoint.java
create mode 100644 chatto/src/main/java/org/ros/chatto/WebConfig.java
create mode 100644 chatto/src/main/java/org/ros/chatto/controller/ChatMessageController.java
create mode 100644 chatto/src/main/java/org/ros/chatto/datae.sql
create mode 100644 chatto/src/main/java/org/ros/chatto/dto/ChatMessageDTO.java
create mode 100644 chatto/src/main/java/org/ros/chatto/dto/UserPublicDTO.java
create mode 100644 chatto/src/main/java/org/ros/chatto/scheme.sql
create mode 100644 chatto/src/main/java/org/ros/chatto/service/ChatService.java
create mode 100644 chatto/src/main/java/org/ros/chatto/service/ChatServiceImpl.java
create mode 100644 chatto/src/main/java/org/ros/chatto/service/MyConversionService.java
create mode 100644 chatto/src/main/resources/static/css/master.css
create mode 100644 chatto/src/main/resources/static/js/chat.js
create mode 100644 chatto/src/main/resources/static/js/loginPage.js
create mode 100644 chatto/src/main/resources/static/js/my_Crypto.js
create mode 100644 chatto/src/main/resources/static/js/scljs.js
create mode 100644 chatto/src/main/resources/templates/chat.html
create mode 100644 chatto/src/main/resources/templates/crypto.html
create mode 100644 chatto/src/main/resources/templates/fragments/head.html
create mode 100644 chatto/src/main/resources/templates/restLogout.html
diff --git a/chatto/pom.xml b/chatto/pom.xml
index 13ba685..ec9dfd3 100644
--- a/chatto/pom.xml
+++ b/chatto/pom.xml
@@ -51,10 +51,7 @@
spring-boot-starter-test
test
-
- org.springframework.boot
- spring-boot-starter-freemarker
-
+
org.springframework.boot
spring-boot-starter-thymeleaf
@@ -74,12 +71,19 @@
2.1.2
-
+
org.projectlombok
lombok
+
+
+ org.modelmapper
+ modelmapper
+ 2.3.5
+
+
diff --git a/chatto/src/main/java/org/ros/chatto/BeanConfigurations.java b/chatto/src/main/java/org/ros/chatto/BeanConfigurations.java
index d457bce..eb1da74 100644
--- a/chatto/src/main/java/org/ros/chatto/BeanConfigurations.java
+++ b/chatto/src/main/java/org/ros/chatto/BeanConfigurations.java
@@ -1,5 +1,6 @@
-package org.ros.chatto.controller;
+package org.ros.chatto;
+import org.modelmapper.ModelMapper;
import org.ros.chatto.security.AuthenticationSuccessHandlerImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -7,9 +8,16 @@ import org.springframework.security.web.authentication.AuthenticationSuccessHand
@Configuration
public class BeanConfigurations {
-
- @Bean
- public AuthenticationSuccessHandler authenticationSuccessHandler() {
- return new AuthenticationSuccessHandlerImpl();
- }
+
+ @Bean
+ public AuthenticationSuccessHandler authenticationSuccessHandler() {
+ return new AuthenticationSuccessHandlerImpl();
+ }
+
+ @Bean
+ public ModelMapper modelMapper() {
+ ModelMapper modelMapper = new ModelMapper();
+ return modelMapper;
+ }
+
}
diff --git a/chatto/src/main/java/org/ros/chatto/ChattoApplication.java b/chatto/src/main/java/org/ros/chatto/ChattoApplication.java
index 8fa00f5..66d5461 100644
--- a/chatto/src/main/java/org/ros/chatto/ChattoApplication.java
+++ b/chatto/src/main/java/org/ros/chatto/ChattoApplication.java
@@ -12,6 +12,7 @@ public class ChattoApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(ChattoApplication.class, args);
+
}
@Override
diff --git a/chatto/src/main/java/org/ros/chatto/RestAuthenticationEntryPoint.java b/chatto/src/main/java/org/ros/chatto/RestAuthenticationEntryPoint.java
new file mode 100644
index 0000000..83550e9
--- /dev/null
+++ b/chatto/src/main/java/org/ros/chatto/RestAuthenticationEntryPoint.java
@@ -0,0 +1,42 @@
+package org.ros.chatto;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+@Component
+public final class RestAuthenticationEntryPoint
+ extends BasicAuthenticationEntryPoint {
+
+// @Override
+// public void commence(
+// HttpServletRequest request,
+// HttpServletResponse response,
+// AuthenticationException authException) throws IOException {
+//
+// response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
+// "Unauthorized");
+// }
+
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
+ throws IOException, ServletException {
+ response.addHeader("WWW-Authenticate", "Basic realm=" +getRealmName());
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ PrintWriter writer = response.getWriter();
+ writer.println("HTTP Status 401 - " + authEx.getMessage());
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ setRealmName("Chatto");
+ super.afterPropertiesSet();
+ }
+}
diff --git a/chatto/src/main/java/org/ros/chatto/WebConfig.java b/chatto/src/main/java/org/ros/chatto/WebConfig.java
new file mode 100644
index 0000000..f2c7136
--- /dev/null
+++ b/chatto/src/main/java/org/ros/chatto/WebConfig.java
@@ -0,0 +1,20 @@
+package org.ros.chatto;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+//@EnableWebMvc
+public class WebConfig implements WebMvcConfigurer {
+
+ @Override
+ public void addCorsMappings(CorsRegistry registry) {
+ registry.addMapping("/api/**")
+ .allowedOrigins("*")
+ .allowedMethods("POST","GET","OPTIONS")
+ .allowedHeaders("*")
+ .allowCredentials(false).maxAge(3600);
+
+ }
+}
\ No newline at end of file
diff --git a/chatto/src/main/java/org/ros/chatto/WebSecurityConfiguration.java b/chatto/src/main/java/org/ros/chatto/WebSecurityConfiguration.java
index 631f068..e5a1437 100644
--- a/chatto/src/main/java/org/ros/chatto/WebSecurityConfiguration.java
+++ b/chatto/src/main/java/org/ros/chatto/WebSecurityConfiguration.java
@@ -4,7 +4,7 @@ import org.ros.chatto.security.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.http.HttpMethod;
+import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -18,69 +18,119 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
-
- @Autowired
- private AuthenticationSuccessHandler authenticationSuccessHandler;
- @Autowired
- private MyUserDetailsService myUserDetailsService;
- @Autowired
- private PasswordEncoder passwordEncoder;
+
+ @Autowired
+ private AuthenticationSuccessHandler authenticationSuccessHandler;
+ @Autowired
+ private MyUserDetailsService myUserDetailsService;
+ @Autowired
+ private PasswordEncoder passwordEncoder;
+
+
// @SuppressWarnings("deprecation")
@Bean
- public AuthenticationProvider authenticationProvider()
- {
+ public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(myUserDetailsService);
provider.setPasswordEncoder(passwordEncoder);
return provider;
}
+
@Bean
public static PasswordEncoder passwordEncoder() {
- return new BCryptPasswordEncoder();
+ return new BCryptPasswordEncoder();
+ }
+
+
+
+ @Configuration
+ @Order(1)
+ public static class ApiWebSecurity extends WebSecurityConfigurerAdapter {
+ @Autowired
+ private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .csrf().disable()
+ .exceptionHandling()
+
+ .and()
+// .cors().and()
+ .antMatcher("/api/**")
+ .authorizeRequests()
+// .antMatchers("/perform-login").permitAll()
+ .anyRequest()
+// .hasAnyRole("USER", "ADMIN", "SUPER_USER")
+ .authenticated()
+ .and().httpBasic()
+ .authenticationEntryPoint(restAuthenticationEntryPoint)
+// .and()
+// .logout().invalidateHttpSession(true).clearAuthentication(true)
+// .logoutRequestMatcher(new AntPathRequestMatcher("/api/perform_logout"))
+// .logoutSuccessUrl("/").permitAll()
+// .and()
+// .formLogin()
+// .loginProcessingUrl("/api/perform_login").permitAll()
+// .and()
+// .formLogin()
+// .and()
+// .logout();
+ ;
+
+ }
+
+ }
+
+ @Configuration
+ @Order(2)
+ public static class FormWebSecurity extends WebSecurityConfigurerAdapter {
+ @Override
+
+ protected void configure(HttpSecurity httpSecurity) throws Exception {
+ httpSecurity.authorizeRequests()
+// .antMatchers(HttpMethod.POST, "/api/**").permitAll()
+ .antMatchers("/", "perform_login","/login*", "/registration", "/perform_registration", "/css/**", "/js/**",
+ "/images/**")
+ .permitAll()
+// .antMatchers("/","/api**","/api/**","/login*","/registration","/perform_registration","/css/**", "/js/**", "/images/**").permitAll()
+ .antMatchers("/user/**").hasAnyRole("USER", "ADMIN", "SUPER_USER")
+ .antMatchers("/admin/**").hasAnyRole("ADMIN", "SUPER_USER")
+// .and()
+// .antMatcher("/api/**")
+// .authorizeRequests()
+ .anyRequest().authenticated()
+
+ .and()
+
+ .formLogin()
+ .loginPage("/login").permitAll()
+ .loginProcessingUrl("/login")
+// .successHandler(authenticationSuccessHandler)
+// .failureUrl("/?login_error")
+ .and()
+ .logout().invalidateHttpSession(true).clearAuthentication(true)
+ .logoutRequestMatcher(new AntPathRequestMatcher("/perform_logout"))
+// .logoutSuccessUrl("/").permitAll()
+// .and().httpBasic();
+// .and().cors()
+// .and().csrf().disable();
+ ;
+// httpSecurity
+// .csrf().disable()
+// .authorizeRequests().antMatchers("login").permitAll()
+// .anyRequest().authenticated()
+// .and()
+// .formLogin()
+// .loginPage("/login").permitAll()
+// .and()
+// .logout().invalidateHttpSession(true)
+// .clearAuthentication(true)
+// .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
+// .logoutSuccessUrl("/").permitAll();
+
+ }
}
- @Override
- protected void configure(HttpSecurity httpSecurity) throws Exception {
- httpSecurity.authorizeRequests()
- .antMatchers(HttpMethod.POST, "/api/**").permitAll()
- .antMatchers("/","/login*","/registration","/perform_registration","/css/**", "/js/**", "/images/**").permitAll()
-// .antMatchers("/","/api**","/api/**","/login*","/registration","/perform_registration","/css/**", "/js/**", "/images/**").permitAll()
- .antMatchers("/user/**").hasAnyRole("USER", "ADMIN","SUPER_USER")
- .antMatchers("/admin/**").hasAnyRole("ADMIN","SUPER_USER")
- .anyRequest()
- .authenticated()
-
- .and()
-
- .formLogin()
-// .loginPage("/login").permitAll()
- .loginProcessingUrl("/perform_login")
-// .successHandler(authenticationSuccessHandler)
- .failureUrl("/?login_error")
- .and()
- .logout().invalidateHttpSession(true)
- .clearAuthentication(true)
- .logoutRequestMatcher(new AntPathRequestMatcher("/perform_logout"))
- .logoutSuccessUrl("/").permitAll()
- .and().cors().and().csrf().disable();
-
-
-
-// httpSecurity
-// .csrf().disable()
-// .authorizeRequests().antMatchers("login").permitAll()
-// .anyRequest().authenticated()
-// .and()
-// .formLogin()
-// .loginPage("/login").permitAll()
-// .and()
-// .logout().invalidateHttpSession(true)
-// .clearAuthentication(true)
-// .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
-// .logoutSuccessUrl("/").permitAll();
-
- }
-
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.inMemoryAuthentication()
@@ -113,6 +163,6 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
// auth.userDetailsService(myUserDetailsService);
// }
// auth.userDetailsService(myUserDetailsService);
-
+
// }
}
diff --git a/chatto/src/main/java/org/ros/chatto/controller/ChatMessageController.java b/chatto/src/main/java/org/ros/chatto/controller/ChatMessageController.java
new file mode 100644
index 0000000..11e8aa8
--- /dev/null
+++ b/chatto/src/main/java/org/ros/chatto/controller/ChatMessageController.java
@@ -0,0 +1,76 @@
+package org.ros.chatto.controller;
+
+import java.security.Principal;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.util.Date;
+import java.util.List;
+
+import org.ros.chatto.dto.ChatMessageDTO;
+import org.ros.chatto.model.MessageCipher;
+import org.ros.chatto.service.ChatService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/api/chat")
+public class ChatMessageController {
+ @Autowired
+ private ChatService chatService;
+
+ @PostMapping(value = "/post/message", consumes = { "application/json" })
+ @ResponseBody
+ public ResponseEntity newMessage(@RequestBody ChatMessageDTO chatMessageDTO, Principal principal) {
+ MessageCipher 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(HttpStatus.OK);
+ }
+
+ @GetMapping(value = "/get/messages/{userName}")
+ @ResponseBody
+ public List sendAllMessages(@PathVariable String userName, Principal principal) {
+ List chatMessageDTOs = chatService.getAllMessages(principal.getName(), userName);
+ return chatMessageDTOs;
+ }
+ @GetMapping(value = "/get/messages/{userName}/{lastMessageTime}")
+ @ResponseBody
+ public List sendNewMessages(@PathVariable String userName, @PathVariable String lastMessageTime, Principal principal) {
+ System.out.println("Last message time = " + lastMessageTime );
+ DateTimeFormatter formatter = new DateTimeFormatterBuilder()
+ // date/time
+ .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
+ // offset (hh:mm - "+00:00" when it's zero)
+ .optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
+ // offset (hhmm - "+0000" when it's zero)
+ .optionalStart().appendOffset("+HHMM", "+0000").optionalEnd()
+ // offset (hh - "Z" when it's zero)
+ .optionalStart().appendOffset("+HH", "Z").optionalEnd()
+ // create formatter
+ .toFormatter();
+ Date date = Date.from(OffsetDateTime.parse(lastMessageTime, formatter).toInstant());
+
+ List chatMessageDTOs = chatService.getNewMessages(principal.getName(), userName, date);
+ return chatMessageDTOs;
+ }
+}
+
+//public ResponseEntity> getMessages(@PathVariable String userName, Principal principal) {
+////List chatMessages = chatMessageRepository.getAllMessages(principal.getName(), userName);
+//
+//// return posts.stream()
+//// .map(post -> convertToDto(post))
+//// .collect(Collectors.toList());
+//return new ResponseEntity>(chatMessages, HttpStatus.OK);
+//}
diff --git a/chatto/src/main/java/org/ros/chatto/controller/DemoRestController.java b/chatto/src/main/java/org/ros/chatto/controller/DemoRestController.java
index 76b315f..4b7f7a1 100644
--- a/chatto/src/main/java/org/ros/chatto/controller/DemoRestController.java
+++ b/chatto/src/main/java/org/ros/chatto/controller/DemoRestController.java
@@ -1,27 +1,38 @@
package org.ros.chatto.controller;
-import org.ros.chatto.repository.UserRepositoryCustom;
-import org.ros.chatto.repository.UserRoleRepository;
+import java.security.Principal;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.ros.chatto.model.ChatMessage;
+import org.ros.chatto.model.ChatUser;
+import org.ros.chatto.model.MessageCipher;
+import org.ros.chatto.model.UserRole;
+import org.ros.chatto.repository.ChatMessageRepository;
import org.ros.chatto.repository.MessageCipherRepository;
import org.ros.chatto.repository.RoleRepository;
import org.ros.chatto.repository.UserRepository;
+import org.ros.chatto.repository.UserRepositoryCustom;
+import org.ros.chatto.repository.UserRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
-
-import java.util.List;
-
-import org.ros.chatto.model.ChatUser;
-import org.ros.chatto.model.MessageCipher;
-import org.ros.chatto.model.UserRole;
+import org.springframework.web.servlet.ModelAndView;
@RestController
@RequestMapping("/api")
+//@CrossOrigin(origins = "*", allowCredentials = "true", allowedHeaders = "*")
public class DemoRestController {
@Autowired
@@ -34,6 +45,8 @@ public class DemoRestController {
UserRoleRepository userRoleRepository;
@Autowired
MessageCipherRepository messageCipherRepository;
+ @Autowired
+ ChatMessageRepository chatMessageRepository;
@GetMapping("/users")
public List getAllUsers() {
@@ -45,23 +58,35 @@ public class DemoRestController {
return userRepositoryCustom.getAllUserNames("hmm");
}
- @GetMapping("/user")
+ @GetMapping("/user_old")
public ChatUser getUser() {
return userRepository.findByUserName("hmm");
}
+ @GetMapping("/user")
+ public ChatUser currentUserName(Principal principal) {
+ ChatUser user = userRepository.findByUserName(principal.getName());
+ return user;
+ }
+
@GetMapping("/roles")
public List getAllRoles()
{
return userRoleRepository.findAll();
}
- @GetMapping("/messages")
+ @GetMapping("/ciphers")
public List getAllCiphers()
{
return messageCipherRepository.findAll();
}
+ @GetMapping("/messages")
+ public List getAllMessages()
+ {
+ return chatMessageRepository.findAll();
+ }
+
// @RequestMapping(value = "/", method = RequestMethod.POST)
// public ResponseEntity update(@RequestBody Car car) {
//
@@ -80,5 +105,20 @@ public class DemoRestController {
messageCipherRepository.save(messageCipher);
return new ResponseEntity(HttpStatus.OK);
}
+
+ @GetMapping("/logout")
+ public ModelAndView logoutPage()
+ {
+ ModelAndView modelAndView = new ModelAndView("restLogout");
+ return modelAndView;
+ }
+ @RequestMapping(value="perform_logout", method = RequestMethod.POST)
+ public String performLogout (HttpServletRequest request, HttpServletResponse response) {
+ Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+ if (auth != null){
+ new SecurityContextLogoutHandler().logout(request, response, auth);
+ }
+ return "redirect:/users";
+ }
}
diff --git a/chatto/src/main/java/org/ros/chatto/controller/Home.java b/chatto/src/main/java/org/ros/chatto/controller/Home.java
index 20b3d32..e68572c 100644
--- a/chatto/src/main/java/org/ros/chatto/controller/Home.java
+++ b/chatto/src/main/java/org/ros/chatto/controller/Home.java
@@ -1,7 +1,14 @@
package org.ros.chatto.controller;
-import org.ros.chatto.repository.UserRepositoryCustom;
+
+import java.security.Principal;
+
+import org.ros.chatto.dto.ChatMessageDTO;
+import org.ros.chatto.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@@ -23,15 +30,46 @@ public class TestController {
@Controller
public class Home {
+
@Autowired
- UserRepositoryCustom userRepositoryCustom;
+ UserService userService;
+
@RequestMapping("/")
- public ModelAndView showPage() {
+ public ModelAndView showPage(Principal principal) {
ModelAndView mv = new ModelAndView("home");
mv.addObject("message", "Welcome!");
- mv.addObject("userNames", userRepositoryCustom.getAllUserNames("hmm"));
+// mv.addObject("userNames", userService.findAllOtherUsers(principal.getName()));
return mv;
}
+
+ @GetMapping("/crypt")
+ public String showCrypt() {
+ return "crypto";
+ }
+
+ @GetMapping("/chat")
+ public ModelAndView showChat(Principal principal) {
+ ModelAndView modelAndView = new ModelAndView("chat");
+ modelAndView.addObject(new ChatMessageDTO());
+// modelAndView.addObject("userNames", userRepositoryCustom.getAllUserNames("hmm"));
+
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+
+// Set roles = authentication.getAuthorities().stream().map(r -> r.getAuthority())
+// .collect(Collectors.toSet());
+// for (String r : roles) {
+// System.out.println(r);
+// }
+
+// boolean hasUserRole = authentication.getAuthorities().stream()
+// .anyMatch(r -> r.getAuthority().equals("ROLE_USER"));
+
+ boolean isAdmin = authentication.getAuthorities().stream()
+ .anyMatch(r -> r.getAuthority().equals("ROLE_ADMIN") || r.getAuthority().equals("ROLE_SUPER_USER"));
+ System.out.println("Is admin? " + isAdmin);
+ modelAndView.addObject("userNames", userService.findAllOtherUsers(principal.getName()));
+ return modelAndView;
+ }
// public String showHome(Model model)
// {
// model.addAttribute("message", "Welcome");
diff --git a/chatto/src/main/java/org/ros/chatto/controller/RegisterController.java b/chatto/src/main/java/org/ros/chatto/controller/RegisterController.java
index a13e786..23767aa 100644
--- a/chatto/src/main/java/org/ros/chatto/controller/RegisterController.java
+++ b/chatto/src/main/java/org/ros/chatto/controller/RegisterController.java
@@ -3,7 +3,7 @@ package org.ros.chatto.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.ros.chatto.model.UserDTO;
+import org.ros.chatto.dto.UserRegistrationDTO;
import org.ros.chatto.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@@ -21,14 +21,14 @@ public class RegisterController {
public ModelAndView registrationForm()
{
ModelAndView modelAndView = new ModelAndView("registration");
- modelAndView.addObject("userDTO",new UserDTO());
+ modelAndView.addObject("userDTO",new UserRegistrationDTO());
return modelAndView;
}
@PostMapping("/perform_registration")
- public ModelAndView performRegistration(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, @ModelAttribute("userDTO") UserDTO userDTO)
+ public ModelAndView performRegistration(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, @ModelAttribute("userDTO") UserRegistrationDTO userRegistrationDTO)
{
ModelAndView modelAndView = new ModelAndView("user/home");
- userService.registerUser(userDTO);
+ userService.registerUser(userRegistrationDTO);
return modelAndView;
}
}
diff --git a/chatto/src/main/java/org/ros/chatto/datae.sql b/chatto/src/main/java/org/ros/chatto/datae.sql
new file mode 100644
index 0000000..c014ab3
--- /dev/null
+++ b/chatto/src/main/java/org/ros/chatto/datae.sql
@@ -0,0 +1,39 @@
+--INSERT INTO `admins` (`admin_id`, `user_id`) VALUES
+--(1, 3);
+--INSERT INTO `chat_messages` (`m_id`, `from_user`, `to_user`, `message`, `message_time`) VALUES
+--(5, 3, 6, 3, '2019-09-28 15:42:15'),
+--(6, 8, 3, 9, '2019-09-30 10:38:18'),
+--(7, 8, 6, 10, '2019-09-30 10:40:31'),
+--(8, 8, 3, 11, '2019-09-30 10:42:54'),
+--(9, 3, 8, 4, '2019-09-30 12:40:16'),
+--(10, 8, 3, 12, '2019-09-30 13:47:41'),
+--(11, 8, 13, 13, '2019-09-30 13:47:48'),
+--(12, 8, 6, 14, '2019-09-30 13:48:00'),
+--(13, 8, 3, 15, '2019-10-01 06:34:10'),
+--(14, 8, 3, 16, '2019-10-01 06:37:19'),
+--(15, 8, 13, 17, '2019-10-01 06:56:07'),
+--(16, 8, 13, 18, '2019-10-01 20:42:32'),
+--(17, 3, 6, 19, '2019-10-01 20:44:59'),
+--(18, 3, 13, 20, '2019-10-02 04:47:23'),
+--(19, 3, 8, 21, '2019-10-02 04:56:07'),
+--(20, 3, 8, 22, '2019-10-02 04:56:19'),
+--(21, 3, 3, 23, '2019-10-02 06:42:21'),
+--(22, 8, 3, 24, '2019-10-02 07:14:02'),
+--(23, 3, 8, 25, '2019-10-02 09:07:13'),
+--(24, 8, 13, 26, '2019-10-02 09:17:28'),
+--(25, 8, 3, 27, '2019-10-02 09:18:54'),
+--(26, 8, 3, 28, '2019-10-02 09:20:49'),
+--(27, 3, 8, 29, '2019-10-02 09:47:29'),
+--(28, 3, 8, 30, '2019-10-02 09:47:58'),
+--(29, 3, 8, 31, '2019-10-02 10:14:32');
+--
+--INSERT INTO `chatmessage` (`Id`, `Message`, `userName`, `MsgTime`, `colorSelected`) VALUES
+--(400, '', 'dae', '2019/08/19 12:58:52', '333'),
+--(401, 'aegqe\n', 'dae', '2019/08/19 12:58:52', '333');
+--
+--
+--INSERT INTO `users` (`user_id`, `name`, `password`, `join_date`) VALUES
+--(3, 'user2', '$2a$10$nLhkNrGu0/2ahSlULoQ0ROvUK2sRTEZBV014BLB/W9nBSMxy0rTGy', '2019-09-23 07:44:59'),
+--(6, 'novo', '$2a$10$nLhkNrGu0/2ahSlULoQ0ROvUK2sRTEZBV014BLB/W9nBSMxy0rTGy', '2019-09-23 07:45:06'),
+--(8, 'hmm', '$2a$10$k4tASmvqJ1mPA7avuzAnSO1KmWOmNhp7K8Y5Yg.dV/VXMX2L73/Ma', '2019-09-23 07:40:56'),
+--(13, 'hmm2', '$2a$10$F.lMGPDXOguXWehMf1fvq.7XqzbFZWweLv3DYwB.1zpDEuPDcKBv6', '2019-09-23 13:46:33');
\ No newline at end of file
diff --git a/chatto/src/main/java/org/ros/chatto/dto/ChatMessageDTO.java b/chatto/src/main/java/org/ros/chatto/dto/ChatMessageDTO.java
new file mode 100644
index 0000000..2515e7b
--- /dev/null
+++ b/chatto/src/main/java/org/ros/chatto/dto/ChatMessageDTO.java
@@ -0,0 +1,14 @@
+package org.ros.chatto.dto;
+
+import java.util.Date;
+
+import org.ros.chatto.model.MessageCipher;
+
+import lombok.Data;
+
+@Data
+public class ChatMessageDTO {
+ private String toUser, fromUser;
+ private MessageCipher messageCipher;
+ private Date messageTime;
+}
diff --git a/chatto/src/main/java/org/ros/chatto/dto/UserPublicDTO.java b/chatto/src/main/java/org/ros/chatto/dto/UserPublicDTO.java
new file mode 100644
index 0000000..781b6e8
--- /dev/null
+++ b/chatto/src/main/java/org/ros/chatto/dto/UserPublicDTO.java
@@ -0,0 +1,14 @@
+package org.ros.chatto.dto;
+
+import java.sql.Date;
+
+import org.ros.chatto.model.MessageCipher;
+
+import lombok.Data;
+
+@Data
+public class UserPublicDTO {
+ String fromUser, toUser;
+ MessageCipher messageCipher;
+ Date messageTime;
+}
diff --git a/chatto/src/main/java/org/ros/chatto/dto/UserRegistrationDTO.java b/chatto/src/main/java/org/ros/chatto/dto/UserRegistrationDTO.java
index fd3b718..7b780f1 100644
--- a/chatto/src/main/java/org/ros/chatto/dto/UserRegistrationDTO.java
+++ b/chatto/src/main/java/org/ros/chatto/dto/UserRegistrationDTO.java
@@ -1,8 +1,8 @@
-package org.ros.chatto.model;
+package org.ros.chatto.dto;
import javax.persistence.Transient;
-public class UserDTO {
+public class UserRegistrationDTO {
private String userName;
@Transient
private String password;
diff --git a/chatto/src/main/java/org/ros/chatto/model/ChatMessage.java b/chatto/src/main/java/org/ros/chatto/model/ChatMessage.java
index 82ac76c..ed0c883 100644
--- a/chatto/src/main/java/org/ros/chatto/model/ChatMessage.java
+++ b/chatto/src/main/java/org/ros/chatto/model/ChatMessage.java
@@ -29,7 +29,9 @@ public class ChatMessage {
@OneToOne
@JoinColumn(name = "to_user")
private ChatUser toUser;
- private String message;
+ @OneToOne
+ @JoinColumn(name = "message")
+ private MessageCipher messageCipher;
@Temporal(TemporalType.TIMESTAMP)
private Date messageTime;
}
diff --git a/chatto/src/main/java/org/ros/chatto/model/Role.java b/chatto/src/main/java/org/ros/chatto/model/Role.java
index a782ff5..ce2d831 100644
--- a/chatto/src/main/java/org/ros/chatto/model/Role.java
+++ b/chatto/src/main/java/org/ros/chatto/model/Role.java
@@ -3,6 +3,7 @@ package org.ros.chatto.model;
import java.util.HashSet;
import java.util.Set;
+import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
@@ -21,7 +22,7 @@ public class Role {
@Column(name = "role_name")
private String name;
private String description;
- @OneToMany(mappedBy = "role")
+ @OneToMany(mappedBy = "role", cascade = CascadeType.ALL)
@JsonBackReference
private Set userRoles = new HashSet<>();
public int getRoleId() {
diff --git a/chatto/src/main/java/org/ros/chatto/repository/ChatMessageRepository.java b/chatto/src/main/java/org/ros/chatto/repository/ChatMessageRepository.java
index eea47c5..e26e060 100644
--- a/chatto/src/main/java/org/ros/chatto/repository/ChatMessageRepository.java
+++ b/chatto/src/main/java/org/ros/chatto/repository/ChatMessageRepository.java
@@ -1,8 +1,25 @@
package org.ros.chatto.repository;
+import java.util.Date;
+import java.util.List;
+
import org.ros.chatto.model.ChatMessage;
import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+@Repository
public interface ChatMessageRepository extends JpaRepository {
-
+// @Query("select r from RoleRepository where name = ?1")
+// @Query("select ur from UserRole ur where ur.user.userID = ?1")
+// @Query("select m from ChatMessage m where m.toUser.userID = ?1 or m.toUser.userID = ?2 and "
+// + "m.fromUser.userID = ?1 or m.fromUser.userID = ?2 order by m.messageTime asc")
+ @Query("select m from ChatMessage m where (m.toUser.userName = ?1 or m.toUser.userName = ?2) and "
+ + "(m.fromUser.userName = ?1 or m.fromUser.userName = ?2) order by m.messageTime asc")
+ public List getAllMessages(String fromUser, String toUser);
+
+ @Query("select m from ChatMessage m where (m.toUser.userName = ?1 or m.toUser.userName = ?2) and "
+ + "(m.fromUser.userName = ?1 or m.fromUser.userName = ?2) and"
+ + "(m.messageTime >= ?3) order by m.messageTime asc")
+ public List getNewMessages(String fromUser, String toUser, Date lastMessageTime);
}
diff --git a/chatto/src/main/java/org/ros/chatto/repository/UserRepositoryCustomImpl.java b/chatto/src/main/java/org/ros/chatto/repository/UserRepositoryCustomImpl.java
index 339d9ed..73fffdf 100644
--- a/chatto/src/main/java/org/ros/chatto/repository/UserRepositoryCustomImpl.java
+++ b/chatto/src/main/java/org/ros/chatto/repository/UserRepositoryCustomImpl.java
@@ -30,10 +30,10 @@ class UserRepositoryCustomImpl implements UserRepositoryCustom{
criteriaQuery.where(criteriaBuilder.notEqual(root.get("userName"), userName));
userNamesList = entityManager.createQuery(criteriaQuery).getResultList();
- for(String un: userNamesList)
- {
- System.out.println(un);
- }
+// for(String un: userNamesList)
+// {
+// System.out.println(un);
+// }
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
diff --git a/chatto/src/main/java/org/ros/chatto/scheme.sql b/chatto/src/main/java/org/ros/chatto/scheme.sql
new file mode 100644
index 0000000..9001901
--- /dev/null
+++ b/chatto/src/main/java/org/ros/chatto/scheme.sql
@@ -0,0 +1,187 @@
+-- Database: `chatto_db`
+--
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `admins`
+--
+
+CREATE TABLE `admins` (
+ `admin_id` int(11) NOT NULL,
+ `user_id` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+--
+-- Dumping data for table `admins`
+--
+
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `chatmessage`
+--
+
+CREATE TABLE `chatmessage` (
+ `Id` int(10) UNSIGNED NOT NULL,
+ `Message` varchar(4000) NOT NULL,
+ `userName` varchar(100) NOT NULL,
+ `MsgTime` varchar(45) NOT NULL,
+ `colorSelected` varchar(45) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `chatmessage`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `chat_messages`
+--
+
+CREATE TABLE `chat_messages` (
+ `m_id` bigint(20) NOT NULL,
+ `from_user` int(11) NOT NULL,
+ `to_user` int(11) NOT NULL,
+ `message` int(10) NOT NULL,
+ `message_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+--
+-- Dumping data for table `chat_messages`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `total_messages`
+--
+
+CREATE TABLE `total_messages` (
+ `t_id` int(101) NOT NULL,
+ `from_user` int(11) NOT NULL,
+ `to_user` int(11) NOT NULL,
+ `total_messages` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `users`
+--
+
+CREATE TABLE `users` (
+ `user_id` int(11) NOT NULL,
+ `name` varchar(10) NOT NULL,
+ `password` varchar(80) NOT NULL,
+ `join_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+--
+-- Dumping data for table `users`
+--
+
+
+--
+-- Indexes for dumped tables
+--
+
+--
+-- Indexes for table `admins`
+--
+ALTER TABLE `admins`
+ ADD PRIMARY KEY (`admin_id`),
+ ADD UNIQUE KEY `user_id_2` (`user_id`),
+ ADD KEY `admin_id` (`admin_id`),
+ ADD KEY `user_id` (`user_id`);
+
+--
+-- Indexes for table `chatmessage`
+--
+ALTER TABLE `chatmessage`
+ ADD PRIMARY KEY (`Id`);
+
+--
+-- Indexes for table `chat_messages`
+--
+ALTER TABLE `chat_messages`
+ ADD PRIMARY KEY (`m_id`),
+ ADD UNIQUE KEY `identifier_message_number` (`m_id`),
+ ADD KEY `identifier_message_number_2` (`m_id`),
+ ADD KEY `from_user` (`from_user`,`to_user`),
+ ADD KEY `message` (`message`),
+ ADD KEY `FOREIGN KEY TO USER IN MESSAGES TABLE` (`to_user`);
+
+--
+-- Indexes for table `total_messages`
+--
+ALTER TABLE `total_messages`
+ ADD PRIMARY KEY (`t_id`),
+ ADD UNIQUE KEY `identifier` (`t_id`);
+
+--
+-- Indexes for table `users`
+--
+ALTER TABLE `users`
+ ADD PRIMARY KEY (`user_id`),
+ ADD UNIQUE KEY `name` (`name`),
+ ADD KEY `user_id` (`user_id`);
+
+--
+-- AUTO_INCREMENT for dumped tables
+--
+
+--
+-- AUTO_INCREMENT for table `admins`
+--
+ALTER TABLE `admins`
+ MODIFY `admin_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
+--
+-- AUTO_INCREMENT for table `chatmessage`
+--
+ALTER TABLE `chatmessage`
+ MODIFY `Id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=402;
+--
+-- AUTO_INCREMENT for table `chat_messages`
+--
+ALTER TABLE `chat_messages`
+ MODIFY `m_id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=30;
+--
+-- AUTO_INCREMENT for table `total_messages`
+--
+ALTER TABLE `total_messages`
+ MODIFY `t_id` int(101) NOT NULL AUTO_INCREMENT;
+--
+-- AUTO_INCREMENT for table `users`
+--
+ALTER TABLE `users`
+ MODIFY `user_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=14;
+--
+-- Constraints for dumped tables
+--
+
+--
+-- Constraints for table `admins`
+--
+ALTER TABLE `admins`
+ ADD CONSTRAINT `fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE;
+
+--
+-- Constraints for table `chat_messages`
+--
+ALTER TABLE `chat_messages`
+ ADD CONSTRAINT `FOREIGN KEY ENC MESSAGE TABLE` FOREIGN KEY (`message`) REFERENCES `message_ciphers` (`id`) ON UPDATE CASCADE,
+ ADD CONSTRAINT `FOREIGN KEY FROM USER IN MESSAGES TABLE` FOREIGN KEY (`from_user`) REFERENCES `users` (`user_id`) ON UPDATE CASCADE,
+ ADD CONSTRAINT `FOREIGN KEY TO USER IN MESSAGES TABLE` FOREIGN KEY (`to_user`) REFERENCES `users` (`user_id`) ON UPDATE CASCADE;
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+
+
+
diff --git a/chatto/src/main/java/org/ros/chatto/service/ChatService.java b/chatto/src/main/java/org/ros/chatto/service/ChatService.java
new file mode 100644
index 0000000..c837ce7
--- /dev/null
+++ b/chatto/src/main/java/org/ros/chatto/service/ChatService.java
@@ -0,0 +1,17 @@
+package org.ros.chatto.service;
+
+import java.util.Date;
+import java.util.List;
+
+import org.ros.chatto.dto.ChatMessageDTO;
+import org.ros.chatto.model.MessageCipher;
+
+public interface ChatService {
+ void saveNewMessage(String fromUser, String toUser , MessageCipher messageCipher);
+
+ List getAllMessages(String fromUser, String toUser);
+
+ List getMessagePage(int page, int size);
+
+ List getNewMessages(String fromUser, String toUser, Date lastMessageTime);
+}
diff --git a/chatto/src/main/java/org/ros/chatto/service/ChatServiceImpl.java b/chatto/src/main/java/org/ros/chatto/service/ChatServiceImpl.java
new file mode 100644
index 0000000..5c37aea
--- /dev/null
+++ b/chatto/src/main/java/org/ros/chatto/service/ChatServiceImpl.java
@@ -0,0 +1,68 @@
+package org.ros.chatto.service;
+
+import java.util.Date;
+import java.util.List;
+
+import org.ros.chatto.dto.ChatMessageDTO;
+import org.ros.chatto.model.ChatMessage;
+import org.ros.chatto.model.ChatUser;
+import org.ros.chatto.model.MessageCipher;
+import org.ros.chatto.repository.ChatMessageRepository;
+import org.ros.chatto.repository.MessageCipherRepository;
+import org.ros.chatto.repository.UserRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ChatServiceImpl implements ChatService {
+
+// @Autowired
+// UserService userService;
+ @Autowired
+ UserRepository userRepository;
+ @Autowired
+ MessageCipherRepository messageCipherRepository;
+ @Autowired
+ ChatMessageRepository chatMessageRepository;
+ @Autowired
+ MyConversionService myConversionService;
+
+ public void saveNewMessage(String fromUserName, String toUserName, MessageCipher messageCipher) {
+
+ ChatUser fromUser = userRepository.findByUserName(fromUserName);
+ ChatUser toUser = userRepository.findByUserName(toUserName);
+ ChatMessage chatMessage = new ChatMessage();
+ messageCipher = messageCipherRepository.save(messageCipher);
+ chatMessage.setMessageCipher(messageCipher);
+ chatMessage.setFromUser(fromUser);
+ chatMessage.setToUser(toUser);
+
+ chatMessageRepository.save(chatMessage);
+
+ }
+
+ @Override
+ public List getAllMessages(String fromUser, String toUser) {
+ List chatMessages = chatMessageRepository.getAllMessages(fromUser, toUser);
+ List chatMessageDTOs = myConversionService.convertToChatMessageDTOs(chatMessages);
+ return chatMessageDTOs;
+ }
+
+ @Override
+ public List getMessagePage(int page, int size) {
+// Sort sort = Sort
+ Page chatMessages = chatMessageRepository.findAll(PageRequest.of(page, size));
+ List chatMessageDTOs = myConversionService.convertToChatMessageDTOs(chatMessages);
+ return chatMessageDTOs;
+ }
+
+ @Override
+ public List getNewMessages(String fromUser, String toUser, Date lastMessageTime) {
+ // TODO Auto-generated method stub
+ List chatMessages = chatMessageRepository.getNewMessages(fromUser, toUser, lastMessageTime);
+// List chatMessageDTOs
+ return myConversionService.convertToChatMessageDTOs(chatMessages);
+ }
+}
diff --git a/chatto/src/main/java/org/ros/chatto/service/MyConversionService.java b/chatto/src/main/java/org/ros/chatto/service/MyConversionService.java
new file mode 100644
index 0000000..bfc024c
--- /dev/null
+++ b/chatto/src/main/java/org/ros/chatto/service/MyConversionService.java
@@ -0,0 +1,58 @@
+package org.ros.chatto.service;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.modelmapper.ModelMapper;
+import org.ros.chatto.dto.ChatMessageDTO;
+import org.ros.chatto.model.ChatMessage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+
+//private PostDto convertToDto(Post post) {
+// PostDto postDto = modelMapper.map(post, PostDto.class);
+// postDto.setSubmissionDate(post.getSubmissionDate(),
+// userService.getCurrentUser().getPreference().getTimezone());
+// return postDto;
+//}
+//
+//
+//private Post convertToEntity(PostDto postDto) throws ParseException {
+// Post post = modelMapper.map(postDto, Post.class);
+// post.setSubmissionDate(postDto.getSubmissionDateConverted(
+// userService.getCurrentUser().getPreference().getTimezone()));
+//
+// if (postDto.getId() != null) {
+// Post oldPost = postService.getPostById(postDto.getId());
+// post.setRedditID(oldPost.getRedditID());
+// post.setSent(oldPost.isSent());
+// }
+// return post;
+//}
+@Service
+public class MyConversionService {
+ @Autowired
+ ModelMapper modelMapper;
+
+ public ChatMessageDTO convertToChatMessageDTO(ChatMessage chatMessage)
+ {
+ ChatMessageDTO chatMessageDTO = modelMapper.map(chatMessage, ChatMessageDTO.class);
+ return chatMessageDTO;
+ }
+
+ public List convertToChatMessageDTOs(List chatMessages)
+ {
+ return chatMessages.stream()
+ .map(chatMessage -> convertToChatMessageDTO(chatMessage))
+ .collect(Collectors.toList());
+ }
+
+ public List convertToChatMessageDTOs(Page chatMessages)
+ {
+ return chatMessages.stream()
+ .map(chatMessage -> convertToChatMessageDTO(chatMessage))
+ .collect(Collectors.toList());
+ }
+}
diff --git a/chatto/src/main/java/org/ros/chatto/service/UserService.java b/chatto/src/main/java/org/ros/chatto/service/UserService.java
index 1941e60..c5f9154 100644
--- a/chatto/src/main/java/org/ros/chatto/service/UserService.java
+++ b/chatto/src/main/java/org/ros/chatto/service/UserService.java
@@ -1,11 +1,14 @@
package org.ros.chatto.service;
+import java.util.List;
+
+import org.ros.chatto.dto.UserRegistrationDTO;
import org.ros.chatto.model.ChatUser;
-import org.ros.chatto.model.UserDTO;
+import org.springframework.stereotype.Service;
-//@Service
+@Service
public interface UserService {
public void saveChatUser(ChatUser user);
-
- public void registerUser(UserDTO userDTO);
+ public List findAllOtherUsers(String userName);
+ public void registerUser(UserRegistrationDTO userRegistrationDTO);
}
diff --git a/chatto/src/main/java/org/ros/chatto/service/UserServiceImpl.java b/chatto/src/main/java/org/ros/chatto/service/UserServiceImpl.java
index 7148f1b..eaf6c00 100644
--- a/chatto/src/main/java/org/ros/chatto/service/UserServiceImpl.java
+++ b/chatto/src/main/java/org/ros/chatto/service/UserServiceImpl.java
@@ -1,10 +1,13 @@
package org.ros.chatto.service;
+import java.util.List;
+
+import org.ros.chatto.dto.UserRegistrationDTO;
import org.ros.chatto.model.ChatUser;
import org.ros.chatto.model.Role;
-import org.ros.chatto.model.UserDTO;
import org.ros.chatto.model.UserRole;
import org.ros.chatto.repository.UserRepository;
+import org.ros.chatto.repository.UserRepositoryCustom;
import org.ros.chatto.repository.UserRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
@@ -23,6 +26,9 @@ public class UserServiceImpl implements UserService{
@Autowired
RoleService roleService;
+
+ @Autowired
+ UserRepositoryCustom userRepositoryCustom;
@Override
public void saveChatUser(ChatUser user) {
@@ -35,11 +41,11 @@ public class UserServiceImpl implements UserService{
}
@Override
- public void registerUser(UserDTO userDTO) {
+ public void registerUser(UserRegistrationDTO userRegistrationDTO) {
// TODO Auto-generated method stub
ChatUser user = new ChatUser();
- user.setUserName(userDTO.getUserName());
- user.setPassword(passwordEncoder.encode(userDTO.getPassword()));
+ user.setUserName(userRegistrationDTO.getUserName());
+ user.setPassword(passwordEncoder.encode(userRegistrationDTO.getPassword()));
ChatUser changedUser = userRepository.save(user);
UserRole userRole = new UserRole();
Role role = roleService.getRole("USER");
@@ -50,4 +56,10 @@ public class UserServiceImpl implements UserService{
userRoleRepository.save(userRole);
}
+ @Override
+ public List findAllOtherUsers(String userName) {
+ // TODO Auto-generated method stub
+ return userRepositoryCustom.getAllUserNames(userName);
+ }
+
}
diff --git a/chatto/src/main/resources/application.properties b/chatto/src/main/resources/application.properties
index c19e2be..a64c327 100644
--- a/chatto/src/main/resources/application.properties
+++ b/chatto/src/main/resources/application.properties
@@ -17,4 +17,7 @@ logging.level.org.springframework.web=DEBUG
logging.level.web=DEBUG
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
-spring.http.log-request-details=true
\ No newline at end of file
+spring.http.log-request-details=true
+#spring.jackson.date-format=yyyy-MM-d
+spring.jackson.serialization.write-dates-as-timestamps=false
+#spring.mvc.static-path-pattern=/static/**
\ No newline at end of file
diff --git a/chatto/src/main/resources/static/css/master.css b/chatto/src/main/resources/static/css/master.css
new file mode 100644
index 0000000..0895505
--- /dev/null
+++ b/chatto/src/main/resources/static/css/master.css
@@ -0,0 +1,24 @@
+.myClass {
+ color: red;
+}
+#body-container {
+ margin: 0 auto 0 auto;
+ max-width: 80%;
+ /* vertical-align: auto; */
+}
+.shadow-sm {
+ width: 50%;
+}
+input[type="radio"]{
+ /*position:fixed;*/
+ opacity:0;
+}
+input[type=radio]+label {
+ font-weight: normal;
+}
+input[type=radio]:checked+label {
+ font-weight: bold;
+}
+input[type=radio]:focus+label {
+ border: 1px dotted #000;
+}
\ No newline at end of file
diff --git a/chatto/src/main/resources/static/js/chat.js b/chatto/src/main/resources/static/js/chat.js
new file mode 100644
index 0000000..7dcb6a0
--- /dev/null
+++ b/chatto/src/main/resources/static/js/chat.js
@@ -0,0 +1,267 @@
+// import { sprintf } from 'sprintf-js';
+// import { vsprintf } from 'sprintf-js';
+/*var off_payment_method = document.getElementsByName('offline_payment_method');
+var ischecked_method = false;
+for ( var i = 0; i < off_payment_method.length; i++) {
+ if(off_payment_method[i].checked) {
+ ischecked_method = true;
+ break;
+ }
+}
+if(!ischecked_method) { //payment method button is not checked
+ alert("Please choose Offline Payment Method");
+}*/
+var toUserRadios = document.getElementsByName('toUser');
+var isCheckedUser = false;
+var chatTextArea = document.getElementById('chatTextArea');
+var passphraseInput = document.getElementById('passphrase');
+var postNewMessageUrl = "http://192.168.1.8:8080/api/chat/post/message";
+var getAllMessagesUrl = "http://192.168.1.8:8080/api/chat/get/messages/";
+var getNewMessagesUrl = "http://192.168.1.8:8080/api/chat/get/messages/";
+// var messageLog = [];
+var username = sessionStorage.getItem('username');
+var password = sessionStorage.getItem('password');
+var authToken = 'Basic ' + btoa(username + ":" + password);
+// var lastMessageTimeStamp;
+
+// console.log(authToken);
+// 'Basic ' + btoa("hmm" + ":" + "hmm")
+
+
+
+
+// var user;
+function getSelectedUser() {
+ for (var i = 0; i < toUserRadios.length; i++) {
+ if (toUserRadios[i].checked) {
+ let user = toUserRadios[i].value;
+ console.log('sending to user = ' + user);
+ isCheckedUser = true;
+ return user;
+ }
+ }
+
+}
+
+// console.log('Credentials = ' + JSON.parse(sessionStorage.getItem('credentials')));
+
+function handleChatForm() {
+ let chatInput = document.getElementById('chatInput');
+ let myForm = document.getElementById('chatMessageForm').addEventListener(
+ 'submit', function (e) {
+ e.preventDefault();
+ let user = getSelectedUser();
+ if (!isCheckedUser) {
+ window.alert('please select a user');
+ return;
+ }
+ // console.log('second user = ' + user);
+ let messageContent = chatInput.value;
+ let localDate = new Date();
+ let messageLine = sprintf('%s %s %s: %s', localDate.toLocaleDateString(), localDate.toLocaleTimeString() ,username, messageContent);
+ chatTextArea.append(messageLine + "\n");
+ // let messageCipher = sjcl.encrypt("password", messageContent);
+ let messageCipher = sjcl.encrypt(passphraseInput.value, messageContent);
+ let messageCipherJson = JSON.parse(messageCipher);
+ // let messageCipherSpring = JSON.stringify(messageCipherJson);
+ // console.log('message cipher json ' + messageCipherJson);
+ // console.log('message cipher string ' + messageCipherSpring);
+ let chatMessageDTO = {
+ "toUser": user,
+ "messageCipher": messageCipherJson
+ }
+ // console.log(chatMessageDTO);
+ // console.log(JSON.stringify(chatMessageDTO));
+ messageSend(JSON.stringify(chatMessageDTO));
+ // sessionStorage.setItem('passphrase', passphraseInput.value);
+ // console.log(sessionStorage.getItem('passphrase'));
+
+ })
+}
+
+function messageSend(chatMessageDTO) {
+ let headers = new Headers();
+ // console.log("Token = " + btoa("hmm" + ":" + "hmm"))
+
+ // headers.append('Accept','application/json')
+ headers.append('Content-Type', 'application/json');
+ headers.append('Authorization', authToken);
+ fetch(postNewMessageUrl, {
+ method: 'POST',
+ headers: headers,
+ body: chatMessageDTO
+ })
+ .then(response => console.log(response));
+}
+
+// function getMessages(toUser) {
+// let headers = new Headers();
+// let messageLog = [];
+// // console.log("Token = " + btoa("hmm" + ":" + "hmm"))
+
+// // headers.append('Accept','application/json')
+// // headers.append('Content-Type', 'application/json');
+// headers.append('Authorization', 'Basic ' + btoa("hmm" + ":" + "hmm"));
+// let myPromise = fetch(getUrl + toUser, {
+// method: 'GET',
+// headers: headers
+// })
+// .then(response => {
+// console.log(response);
+// return response.json();
+// })
+// .then(json => {
+
+// console.log(json);
+// let i = 0;
+// json.forEach(function (obj) {
+// // console.log(obj.toUser);
+// messageCipher = JSON.stringify(obj.messageCipher);
+// console.log(messageCipher);
+// // let message = sjcl.decrypt("password", messageCipher);
+// let message = sjcl.decrypt(passphraseInput.value, messageCipher);
+// let messageLine = sprintf('%s %s: %s \n', obj.messageTime, obj.fromUser, message);
+// console.log(messageLine);
+// // chatTextArea.append(obj.fromUser + ": " + message + "\n");
+// chatTextArea.append(messageLine);
+// messageLog[i++] = messageLine;
+// });
+// console.log(messageLog);
+// // return messageLog;
+
+// });
+// return messageLog;
+// }
+
+// async function getUserAsync(name)
+// {
+// let response = await fetch(`https://api.github.com/users/${name}`);
+// let data = await response.json()
+// return data;
+// }
+
+// getUserAsync('yourUsernameHere')
+// .then(data => console.log(data));
+
+async function getAllMessages(toUser) {
+ let headers = new Headers();
+ // headers.append('Accept','application/json')
+ // headers.append('Content-Type', 'application/json');
+ headers.append('Authorization', authToken);
+ let response = await fetch(getAllMessagesUrl + toUser, {
+ method: 'GET',
+ headers: headers
+ });
+ let data = await response.json();
+ return data;
+}
+
+async function getNewMessages(toUser, lastMessageTimeStamp) {
+ let headers = new Headers();
+ headers.append('Authorization', authToken);
+ let response = await fetch(`${getNewMessagesUrl}${toUser}/${lastMessageTimeStamp}`, {
+ method: 'GET',
+ headers: headers
+ });
+ let data = await response.json();
+ return data;
+}
+
+// getMessages('user2');
+window.EventTarget.prototype.addDelegatedListener = function (type, delegateSelector, listener) {
+ this.addEventListener(type, function (event) {
+ if (event.target && event.target.matches(delegateSelector)) {
+ listener.call(event.target, event)
+ }
+ });
+}
+let parent = document.getElementById('chatMessageForm')
+parent.addDelegatedListener("click", "input[type='radio']", function (event) {
+ // if (sessionStorage.getItem('status') != null) {
+ if (passphraseInput.value == '') {
+ alert('Please input passphrase')
+ return;
+ }
+ console.log(this.value);
+ if (sessionStorage.getItem(this.value) == null) {
+ chatTextArea.textContent = '';
+ getAllMessages(this.value)
+ .then(json => {
+ console.log(json);
+ let i = 0;
+ let messageLog = [];
+ let lastMessageTimeStamp;
+ json.forEach(function (obj) {
+ // console.log(obj.toUser);
+ messageCipher = JSON.stringify(obj.messageCipher);
+ console.log(messageCipher);
+ // let message = sjcl.decrypt("password", messageCipher);
+ let message = sjcl.decrypt(passphraseInput.value, messageCipher);
+ let utcDate = obj.messageTime;
+ lastMessageTimeStamp = utcDate;
+ let localDate = new Date(utcDate);
+ let messageLine = sprintf('%s %s: %s ', localDate, obj.fromUser, message);
+
+ // localDate.``
+ // console.log('localDate = ' + localDate);
+ console.log(messageLine);
+ // chatTextArea.append(obj.fromUser + ": " + message + "\n");
+ chatTextArea.append(messageLine + '\n');
+ messageLog[i++] = messageLine;
+
+ });
+ // console.log('Message log = ' + messageLog);
+ sessionStorage.setItem(this.value, JSON.stringify(messageLog));
+ // sessionStorage.clear();
+ console.log('Last message time = ' + lastMessageTimeStamp);
+ sessionStorage.setItem(this.value + '-time', lastMessageTimeStamp);
+ });
+ }
+ else {
+
+
+ console.log("Stored messages = " + sessionStorage.getItem(this.value));
+ let storedMessages = JSON.parse(sessionStorage.getItem(this.value));
+ getNewMessages(this.value, sessionStorage.getItem(this.value + '-time'))
+ .then(json => {
+ console.log(json)
+ json.forEach(function (obj)
+ {
+ let messageCipher = JSON.stringify(obj.messageCipher);
+ let message = sjcl.decrypt(passphraseInput.value, messageCipher);
+ // console.log(message);
+ // chatTextArea.append(message + "\n");
+ let utcDate = obj.messageTime;
+ lastMessageTimeStamp = utcDate;
+ let localDate = new Date(utcDate);
+ let messageLine = sprintf('%s %s: %s', localDate, obj.fromUser, message);
+
+ // localDate.``
+ // console.log('localDate = ' + localDate);
+ console.log(messageLine);
+ // chatTextArea.append(obj.fromUser + ": " + message + "\n");
+ chatTextArea.append(messageLine + '\n');
+ storedMessages.push(messageLine);
+ })
+ });
+ // sessionStorage.clear();
+ // chatTextArea.append(JSON.stringify(storedMessages));
+ chatTextArea.textContent = '';
+ console.log("Stored messages 2 = " + storedMessages);
+ storedMessages.forEach(function (messageLine) {
+ chatTextArea.append(messageLine + '\n');
+ })
+ }
+ // sessionStorage.setItem('status', 'ready');
+ // sessionStorage.setItem('this.value', messageLog);
+ // console.log('Message log = ' + messageLog);
+ // }
+
+ // let passphraseKey = this.value + '-passphrase';
+ // sessionStorage.setItem(passphraseKey, passphraseInput.value);
+ // console.log(sessionStorage.getItem(passphraseKey));
+});
+
+
+handleChatForm();
+
diff --git a/chatto/src/main/resources/static/js/loginPage.js b/chatto/src/main/resources/static/js/loginPage.js
new file mode 100644
index 0000000..3abf6e1
--- /dev/null
+++ b/chatto/src/main/resources/static/js/loginPage.js
@@ -0,0 +1,19 @@
+
+function storeCredentials() {
+ let usernameInput = document.getElementById('username');
+ let passwordInput = document.getElementById('password');
+ let credentials = {
+ username: usernameInput.value,
+ password: passwordInput.value
+ }
+ // sessionStorage.setItem('credentials', JSON.stringify(credentials));
+ sessionStorage.setItem('username',usernameInput.value);
+ sessionStorage.setItem('password',passwordInput.value);
+}
+
+let loginForm = document.getElementById('loginForm');
+loginForm.addEventListener('submit', function (e) {
+ storeCredentials();
+})
+
+// storeCredentials();
diff --git a/chatto/src/main/resources/static/js/my_Crypto.js b/chatto/src/main/resources/static/js/my_Crypto.js
new file mode 100644
index 0000000..9ef7b37
--- /dev/null
+++ b/chatto/src/main/resources/static/js/my_Crypto.js
@@ -0,0 +1,57 @@
+var cipherText = sjcl.encrypt("password", "data");
+console.log(cipherText);
+var plainText = sjcl.decrypt("password", cipherText);
+console.log(plainText);
+
+var field = document.getElementById('crypt');
+// field.innerText = plainText;
+
+var jsonString = "{\"iv\":\"2rtnuXaJXFuQGO9ncaVkmA==\",\"v\":1,\"iter\":10000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"H1z7o3f6qlQ=\",\"ct\":\"lF9Uno7ihjVv01M8\"}";
+
+var myJSON = JSON.parse(jsonString);
+console.log(myJSON);
+
+// let base64 = require('base-64');
+
+let headers = new Headers();
+console.log("Token = " + btoa("hmm" + ":" + "hmm"))
+
+// headers.append('Accept','application/json')
+// headers.append('Content-Type', 'application/json');
+headers.append('Authorization', 'Basic ' + btoa("hmm" + ":" + "hmm"));
+// headers.append('Authorization', 'Basic aG1tOmhtbQ==');
+
+
+// aG1tOmhtbQ==
+var messageCipher;
+fetch('http://localhost:8080/api/messages', {
+ method: 'GET',
+ headers: headers
+ // credentials: 'include'
+}).then(response => response.json())
+ .then(json => {
+ // console.log('parsed json', JSON.stringify(json)) // access json.body here
+ // console.log('parsed json', json[0].messageCipher);
+ messageCipher = JSON.stringify(json[0].messageCipher);
+ console.log(messageCipher);
+ console.log(sjcl.decrypt("password", messageCipher));
+
+ });
+ // console.log("New message = " + messageCipher);
+
+ // [{"messageID":5,"fromUser":{"userID":3,"userName":"user2","joinDate":1569224699000},"toUser":{"userID":6,"userName":"novo","joinDate":1569224706000},"messageCipher":{"iv":"2rtnuXaJXFuQGO9ncaVkmA==","v":1,"mode":"ccm","adata":"","cipher":"aes","salt":"H1z7o3f6qlQ=","iter":10000,"ks":128,"ts":64,"ct":"lF9Uno7ihjVv01M8"},"messageTime":1569685335000}]
+
+var url = 'http://localhost:8080/api/users'
+xml = new XMLHttpRequest();
+xml.onreadystatechange = function () {
+ if (xml.readyState == XMLHttpRequest.DONE) {
+ // alert(xhr.responseText);
+ console.log(xml.responseText);
+ // console.log(xml.getResponseHeader('X-CSRF-TOKEN'));
+ }
+}
+xml.open('GET', url)
+xml.setRequestHeader('Authorization', 'Basic aG1tOmhtbQ==');
+xml.setRequestHeader("X-CSRF-TOKEN", "fetch");
+xml.send(null);
+
diff --git a/chatto/src/main/resources/static/js/scljs.js b/chatto/src/main/resources/static/js/scljs.js
new file mode 100644
index 0000000..c3c3ea9
--- /dev/null
+++ b/chatto/src/main/resources/static/js/scljs.js
@@ -0,0 +1,60 @@
+"use strict";var sjcl={cipher:{},hash:{},keyexchange:{},mode:{},misc:{},codec:{},exception:{corrupt:function(a){this.toString=function(){return"CORRUPT: "+this.message};this.message=a},invalid:function(a){this.toString=function(){return"INVALID: "+this.message};this.message=a},bug:function(a){this.toString=function(){return"BUG: "+this.message};this.message=a},notReady:function(a){this.toString=function(){return"NOT READY: "+this.message};this.message=a}}};
+sjcl.cipher.aes=function(a){this.s[0][0][0]||this.O();var b,c,d,e,f=this.s[0][4],g=this.s[1];b=a.length;var h=1;if(4!==b&&6!==b&&8!==b)throw new sjcl.exception.invalid("invalid aes key size");this.b=[d=a.slice(0),e=[]];for(a=b;a<4*b+28;a++){c=d[a-1];if(0===a%b||8===b&&4===a%b)c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255],0===a%b&&(c=c<<8^c>>>24^h<<24,h=h<<1^283*(h>>7));d[a]=d[a-b]^c}for(b=0;a;b++,a--)c=d[b&3?a:a-4],e[b]=4>=a||4>b?c:g[0][f[c>>>24]]^g[1][f[c>>16&255]]^g[2][f[c>>8&255]]^g[3][f[c&
+255]]};
+sjcl.cipher.aes.prototype={encrypt:function(a){return t(this,a,0)},decrypt:function(a){return t(this,a,1)},s:[[[],[],[],[],[]],[[],[],[],[],[]]],O:function(){var a=this.s[0],b=this.s[1],c=a[4],d=b[4],e,f,g,h=[],k=[],l,n,m,p;for(e=0;0x100>e;e++)k[(h[e]=e<<1^283*(e>>7))^e]=e;for(f=g=0;!c[f];f^=l||1,g=k[g]||1)for(m=g^g<<1^g<<2^g<<3^g<<4,m=m>>8^m&255^99,c[f]=m,d[m]=f,n=h[e=h[l=h[f]]],p=0x1010101*n^0x10001*e^0x101*l^0x1010100*f,n=0x101*h[m]^0x1010100*m,e=0;4>e;e++)a[e][f]=n=n<<24^n>>>8,b[e][m]=p=p<<24^p>>>8;for(e=
+0;5>e;e++)a[e]=a[e].slice(0),b[e]=b[e].slice(0)}};
+function t(a,b,c){if(4!==b.length)throw new sjcl.exception.invalid("invalid aes block size");var d=a.b[c],e=b[0]^d[0],f=b[c?3:1]^d[1],g=b[2]^d[2];b=b[c?1:3]^d[3];var h,k,l,n=d.length/4-2,m,p=4,r=[0,0,0,0];h=a.s[c];a=h[0];var q=h[1],v=h[2],w=h[3],x=h[4];for(m=0;m>>24]^q[f>>16&255]^v[g>>8&255]^w[b&255]^d[p],k=a[f>>>24]^q[g>>16&255]^v[b>>8&255]^w[e&255]^d[p+1],l=a[g>>>24]^q[b>>16&255]^v[e>>8&255]^w[f&255]^d[p+2],b=a[b>>>24]^q[e>>16&255]^v[f>>8&255]^w[g&255]^d[p+3],p+=4,e=h,f=k,g=l;for(m=
+0;4>m;m++)r[c?3&-m:m]=x[e>>>24]<<24^x[f>>16&255]<<16^x[g>>8&255]<<8^x[b&255]^d[p++],h=e,e=f,f=g,g=b,b=h;return r}
+sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.$(a.slice(b/32),32-(b&31)).slice(1);return void 0===c?a:sjcl.bitArray.clamp(a,c-b)},extract:function(a,b,c){var d=Math.floor(-b-c&31);return((b+c-1^b)&-32?a[b/32|0]<<32-d^a[b/32+1|0]>>>d:a[b/32|0]>>>d)&(1<>b-1,1));return a},partial:function(a,b,c){return 32===a?b:(c?b|0:b<<32-a)+0x10000000000*a},getPartial:function(a){return Math.round(a/0x10000000000)||32},equal:function(a,b){if(sjcl.bitArray.bitLength(a)!==sjcl.bitArray.bitLength(b))return!1;var c=0,d;for(d=0;d>>b),c=a[e]<<32-b;e=a.length?a[a.length-1]:0;a=sjcl.bitArray.getPartial(e);d.push(sjcl.bitArray.partial(b+a&31,32>>24|c>>>8&0xff00|(c&0xff00)<<8|c<<24;return a}};
+sjcl.codec.utf8String={fromBits:function(a){var b="",c=sjcl.bitArray.bitLength(a),d,e;for(d=0;d>>8>>>8>>>8),e<<=8;return decodeURIComponent(escape(b))},toBits:function(a){a=unescape(encodeURIComponent(a));var b=[],c,d=0;for(c=0;c>>g)>>>e),gn){if(!b)try{return sjcl.codec.base32hex.toBits(a)}catch(p){}throw new sjcl.exception.invalid("this isn't "+m+"!");}h>e?(h-=e,f.push(l^n>>>h),l=n<>>e)>>>26),6>e?(g=a[c]<<6-e,e+=26,c++):(g<<=6,e-=6);for(;d.length&3&&!b;)d+="=";return d},toBits:function(a,b){a=a.replace(/\s|=/g,"");var c=[],d,e=0,f=sjcl.codec.base64.B,g=0,h;b&&(f=f.substr(0,62)+"-_");for(d=0;dh)throw new sjcl.exception.invalid("this isn't base64!");26>>e),g=h<<32-e):(e+=6,g^=h<<32-e)}e&56&&c.push(sjcl.bitArray.partial(e&56,g,1));return c}};sjcl.codec.base64url={fromBits:function(a){return sjcl.codec.base64.fromBits(a,1,1)},toBits:function(a){return sjcl.codec.base64.toBits(a,1)}};sjcl.hash.sha256=function(a){this.b[0]||this.O();a?(this.F=a.F.slice(0),this.A=a.A.slice(0),this.l=a.l):this.reset()};sjcl.hash.sha256.hash=function(a){return(new sjcl.hash.sha256).update(a).finalize()};
+sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.F=this.Y.slice(0);this.A=[];this.l=0;return this},update:function(a){"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));var b,c=this.A=sjcl.bitArray.concat(this.A,a);b=this.l;a=this.l=b+sjcl.bitArray.bitLength(a);if(0x1fffffffffffffb;c++){e=!0;for(d=2;d*d<=c;d++)if(0===c%d){e=
+!1;break}e&&(8>b&&(this.Y[b]=a(Math.pow(c,.5))),this.b[b]=a(Math.pow(c,1/3)),b++)}}};
+function u(a,b){var c,d,e,f=a.F,g=a.b,h=f[0],k=f[1],l=f[2],n=f[3],m=f[4],p=f[5],r=f[6],q=f[7];for(c=0;64>c;c++)16>c?d=b[c]:(d=b[c+1&15],e=b[c+14&15],d=b[c&15]=(d>>>7^d>>>18^d>>>3^d<<25^d<<14)+(e>>>17^e>>>19^e>>>10^e<<15^e<<13)+b[c&15]+b[c+9&15]|0),d=d+q+(m>>>6^m>>>11^m>>>25^m<<26^m<<21^m<<7)+(r^m&(p^r))+g[c],q=r,r=p,p=m,m=n+d|0,n=l,l=k,k=h,h=d+(k&l^n&(k^l))+(k>>>2^k>>>13^k>>>22^k<<30^k<<19^k<<10)|0;f[0]=f[0]+h|0;f[1]=f[1]+k|0;f[2]=f[2]+l|0;f[3]=f[3]+n|0;f[4]=f[4]+m|0;f[5]=f[5]+p|0;f[6]=f[6]+r|0;f[7]=
+f[7]+q|0}
+sjcl.mode.ccm={name:"ccm",G:[],listenProgress:function(a){sjcl.mode.ccm.G.push(a)},unListenProgress:function(a){a=sjcl.mode.ccm.G.indexOf(a);-1k)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(f=2;4>f&&l>>>8*f;f++);f<15-k&&(f=15-k);c=h.clamp(c,
+8*(15-f));b=sjcl.mode.ccm.V(a,b,c,d,e,f);g=sjcl.mode.ccm.C(a,g,c,b,e,f);return h.concat(g.data,g.tag)},decrypt:function(a,b,c,d,e){e=e||64;d=d||[];var f=sjcl.bitArray,g=f.bitLength(c)/8,h=f.bitLength(b),k=f.clamp(b,h-e),l=f.bitSlice(b,h-e),h=(h-e)/8;if(7>g)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(b=2;4>b&&h>>>8*b;b++);b<15-g&&(b=15-g);c=f.clamp(c,8*(15-b));k=sjcl.mode.ccm.C(a,k,c,l,e,b);a=sjcl.mode.ccm.V(a,k.data,c,d,e,b);if(!f.equal(k.tag,a))throw new sjcl.exception.corrupt("ccm: tag doesn't match");
+return k.data},na:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,k=h.i;d=[h.partial(8,(b.length?64:0)|d-2<<2|f-1)];d=h.concat(d,c);d[3]|=e;d=a.encrypt(d);if(b.length)for(c=h.bitLength(b)/8,65279>=c?g=[h.partial(16,c)]:0xffffffff>=c&&(g=h.concat([h.partial(16,65534)],[c])),g=h.concat(g,b),b=0;be||16n&&(sjcl.mode.ccm.fa(g/
+k),n+=m),c[3]++,e=a.encrypt(c),b[g]^=e[0],b[g+1]^=e[1],b[g+2]^=e[2],b[g+3]^=e[3];return{tag:d,data:h.clamp(b,l)}}};
+sjcl.mode.ocb2={name:"ocb2",encrypt:function(a,b,c,d,e,f){if(128!==sjcl.bitArray.bitLength(c))throw new sjcl.exception.invalid("ocb iv must be 128 bits");var g,h=sjcl.mode.ocb2.S,k=sjcl.bitArray,l=k.i,n=[0,0,0,0];c=h(a.encrypt(c));var m,p=[];d=d||[];e=e||64;for(g=0;g+4e.bitLength(c)&&(h=f(h,d(h)),c=e.concat(c,[-2147483648,0,0,0]));g=f(g,c);
+return a.encrypt(f(d(f(h,d(h))),g))},S:function(a){return[a[0]<<1^a[1]>>>31,a[1]<<1^a[2]>>>31,a[2]<<1^a[3]>>>31,a[3]<<1^135*(a[0]>>>31)]}};
+sjcl.mode.gcm={name:"gcm",encrypt:function(a,b,c,d,e){var f=b.slice(0);b=sjcl.bitArray;d=d||[];a=sjcl.mode.gcm.C(!0,a,f,d,c,e||128);return b.concat(a.data,a.tag)},decrypt:function(a,b,c,d,e){var f=b.slice(0),g=sjcl.bitArray,h=g.bitLength(f);e=e||128;d=d||[];e<=h?(b=g.bitSlice(f,h-e),f=g.bitSlice(f,0,h-e)):(b=f,f=[]);a=sjcl.mode.gcm.C(!1,a,f,d,c,e);if(!g.equal(a.tag,b))throw new sjcl.exception.corrupt("gcm: tag doesn't match");return a.data},ka:function(a,b){var c,d,e,f,g,h=sjcl.bitArray.i;e=[0,0,
+0,0];f=b.slice(0);for(c=0;128>c;c++){(d=0!==(a[Math.floor(c/32)]&1<<31-c%32))&&(e=h(e,f));g=0!==(f[3]&1);for(d=3;0>>1|(f[d-1]&1)<<31;f[0]>>>=1;g&&(f[0]^=-0x1f000000)}return e},j:function(a,b,c){var d,e=c.length;b=b.slice(0);for(d=0;de&&(a=b.hash(a));for(d=0;dd||0>c)throw new sjcl.exception.invalid("invalid params to pbkdf2");"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));"string"===typeof b&&(b=sjcl.codec.utf8String.toBits(b));e=e||sjcl.misc.hmac;a=new e(a);var f,g,h,k,l=[],n=sjcl.bitArray;for(k=1;32*l.length<(d||1);k++){e=f=a.encrypt(n.concat(b,[k]));for(g=1;gg;g++)e.push(0x100000000*Math.random()|0);for(g=0;g=1<this.o&&(this.o=
+f);this.P++;this.b=sjcl.hash.sha256.hash(this.b.concat(e));this.L=new sjcl.cipher.aes(this.b);for(d=0;4>d&&(this.h[d]=this.h[d]+1|0,!this.h[d]);d++);}for(d=0;d>>1;this.c[g].update([d,this.N++,2,b,f,a.length].concat(a))}break;case "string":void 0===b&&(b=a.length);this.c[g].update([d,this.N++,3,b,f,a.length]);this.c[g].update(a);break;default:k=1}if(k)throw new sjcl.exception.bug("random: addEntropy only supports number, array of numbers or string");this.m[g]+=b;this.f+=b;h===this.u&&(this.isReady()!==this.u&&A("seeded",Math.max(this.o,this.f)),A("progress",this.getProgress()))},
+isReady:function(a){a=this.T[void 0!==a?a:this.M];return this.o&&this.o>=a?this.m[0]>this.ba&&(new Date).valueOf()>this.Z?this.J|this.I:this.I:this.f>=a?this.J|this.u:this.u},getProgress:function(a){a=this.T[a?a:this.M];return this.o>=a?1:this.f>a?1:this.f/a},startCollectors:function(){if(!this.D){this.a={loadTimeCollector:B(this,this.ma),mouseCollector:B(this,this.oa),keyboardCollector:B(this,this.la),accelerometerCollector:B(this,this.ea),touchCollector:B(this,this.qa)};if(window.addEventListener)window.addEventListener("load",
+this.a.loadTimeCollector,!1),window.addEventListener("mousemove",this.a.mouseCollector,!1),window.addEventListener("keypress",this.a.keyboardCollector,!1),window.addEventListener("devicemotion",this.a.accelerometerCollector,!1),window.addEventListener("touchmove",this.a.touchCollector,!1);else if(document.attachEvent)document.attachEvent("onload",this.a.loadTimeCollector),document.attachEvent("onmousemove",this.a.mouseCollector),document.attachEvent("keypress",this.a.keyboardCollector);else throw new sjcl.exception.bug("can't attach event");
+this.D=!0}},stopCollectors:function(){this.D&&(window.removeEventListener?(window.removeEventListener("load",this.a.loadTimeCollector,!1),window.removeEventListener("mousemove",this.a.mouseCollector,!1),window.removeEventListener("keypress",this.a.keyboardCollector,!1),window.removeEventListener("devicemotion",this.a.accelerometerCollector,!1),window.removeEventListener("touchmove",this.a.touchCollector,!1)):document.detachEvent&&(document.detachEvent("onload",this.a.loadTimeCollector),document.detachEvent("onmousemove",
+this.a.mouseCollector),document.detachEvent("keypress",this.a.keyboardCollector)),this.D=!1)},addEventListener:function(a,b){this.K[a][this.ga++]=b},removeEventListener:function(a,b){var c,d,e=this.K[a],f=[];for(d in e)e.hasOwnProperty(d)&&e[d]===b&&f.push(d);for(c=0;cb&&(a.h[b]=a.h[b]+1|0,!a.h[b]);b++);return a.L.encrypt(a.h)}
+function B(a,b){return function(){b.apply(a,arguments)}}sjcl.random=new sjcl.prng(6);
+a:try{var D,E,F,G;if(G="undefined"!==typeof module&&module.exports){var H;try{H=require("crypto")}catch(a){H=null}G=E=H}if(G&&E.randomBytes)D=E.randomBytes(128),D=new Uint32Array((new Uint8Array(D)).buffer),sjcl.random.addEntropy(D,1024,"crypto['randomBytes']");else if("undefined"!==typeof window&&"undefined"!==typeof Uint32Array){F=new Uint32Array(32);if(window.crypto&&window.crypto.getRandomValues)window.crypto.getRandomValues(F);else if(window.msCrypto&&window.msCrypto.getRandomValues)window.msCrypto.getRandomValues(F);
+else break a;sjcl.random.addEntropy(F,1024,"crypto['getRandomValues']")}}catch(a){"undefined"!==typeof window&&window.console&&(console.log("There was an error collecting entropy from the browser:"),console.log(a))}
+sjcl.json={defaults:{v:1,iter:1E4,ks:128,ts:64,mode:"ccm",adata:"",cipher:"aes"},ja:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json,f=e.g({iv:sjcl.random.randomWords(4,0)},e.defaults),g;e.g(f,c);c=f.adata;"string"===typeof f.salt&&(f.salt=sjcl.codec.base64.toBits(f.salt));"string"===typeof f.iv&&(f.iv=sjcl.codec.base64.toBits(f.iv));if(!sjcl.mode[f.mode]||!sjcl.cipher[f.cipher]||"string"===typeof a&&100>=f.iter||64!==f.ts&&96!==f.ts&&128!==f.ts||128!==f.ks&&192!==f.ks&&0x100!==f.ks||2>f.iv.length||
+4=b.iter||64!==b.ts&&96!==b.ts&&128!==b.ts||128!==b.ks&&192!==b.ks&&0x100!==b.ks||!b.iv||2>b.iv.length||4
+
+
+
+
+
+
Chat
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chatto/src/main/resources/templates/crypto.html b/chatto/src/main/resources/templates/crypto.html
new file mode 100644
index 0000000..026bc1b
--- /dev/null
+++ b/chatto/src/main/resources/templates/crypto.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chatto/src/main/resources/templates/fragments/head.html b/chatto/src/main/resources/templates/fragments/head.html
new file mode 100644
index 0000000..37a6d90
--- /dev/null
+++ b/chatto/src/main/resources/templates/fragments/head.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Layout Generic Title
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chatto/src/main/resources/templates/login.html b/chatto/src/main/resources/templates/login.html
index c0a2fc6..ccc2936 100644
--- a/chatto/src/main/resources/templates/login.html
+++ b/chatto/src/main/resources/templates/login.html
@@ -1,17 +1,24 @@
+
-Title
+
+
Login
+
+
-
- Login Page
-
+
+
+
+
\ No newline at end of file
diff --git a/chatto/src/main/resources/templates/registration.html b/chatto/src/main/resources/templates/registration.html
index 4f328fc..4f6eb61 100644
--- a/chatto/src/main/resources/templates/registration.html
+++ b/chatto/src/main/resources/templates/registration.html
@@ -11,6 +11,7 @@
type="text" name="username" id="username">
+
+
+
diff --git a/chatto/src/main/resources/templates/restLogout.html b/chatto/src/main/resources/templates/restLogout.html
new file mode 100644
index 0000000..3624be9
--- /dev/null
+++ b/chatto/src/main/resources/templates/restLogout.html
@@ -0,0 +1,12 @@
+
+
+