add bootstrap to web front-end

This commit is contained in:
Rohan Sircar 2019-10-15 10:58:56 +05:30
parent bb9a4c9b3a
commit 2625cf7865
33 changed files with 1314 additions and 195 deletions

0
chatto/.attach_pid30353 Normal file
View File

View File

@ -5,3 +5,4 @@ spring.datasource.username = chatto_user
spring.datasource.password = password spring.datasource.password = password
database-name = chatto_db2 database-name = chatto_db2
website-url = 192.168.1.13 website-url = 192.168.1.13
test.bindAddress=192.168.1.106

View File

@ -0,0 +1 @@
test.bindAddress=192.168.1.106

View File

@ -0,0 +1,2 @@
#Sat Oct 12 01:13:02 IST 2019
test.bindAddress=192.168.1.106

View File

@ -0,0 +1,2 @@
#Sat Oct 12 01:15:41 IST 2019
test.bindAddress=192.168.1.106

View File

@ -84,6 +84,46 @@
<version>2.3.5</version> <version>2.3.5</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.ehcache/ehcache -->
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.cache/cache-api -->
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.11</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.2.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.thymeleaf.extras/thymeleaf-extras-springsecurity5 -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache -->
<!-- <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId>
</dependency> -->
<!-- <dependency> <groupId>javax.cache</groupId> <artifactId>cache-api</artifactId>
<version>1.1.0</version> </dependency> -->
</dependencies> </dependencies>
<build> <build>

View File

@ -1,15 +1,13 @@
package org.ros.chatto; package org.ros.chatto;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.modelmapper.ModelMapper; import org.modelmapper.ModelMapper;
import org.ros.chatto.security.AuthenticationSuccessHandlerImpl; import org.ros.chatto.security.AuthenticationSuccessHandlerImpl;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
@PropertySource(value = "classpath:queries.properties") @PropertySource(value = "classpath:queries.properties")
@ -36,6 +34,16 @@ public class BeanConfigurations {
return modelMapper; return modelMapper;
} }
@Bean
public MessageSource messageSource() {
final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:/messages,file:./config/messages");
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
messageSource.setCacheSeconds(5);
return messageSource;
}
// @Bean // @Bean
// public Connection connection() throws SQLException // public Connection connection() throws SQLException
// { // {

View File

@ -1,31 +1,38 @@
package org.ros.chatto; package org.ros.chatto;
import java.sql.SQLException;
import org.ros.chatto.service.DBInitializerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
@EnableAutoConfiguration
@SpringBootApplication @SpringBootApplication
//@EnableCaching
public class ChattoApplication extends SpringBootServletInitializer { public class ChattoApplication extends SpringBootServletInitializer {
// @Value("${spring.datasource.url}") // @Value("${spring.datasource.url}")
// private static String url; // private static String url;
public static void main(String[] args) {
public static void main(String[] args) throws SQLException {
SpringApplication application = new SpringApplication(ChattoApplication.class); SpringApplication application = new SpringApplication(ChattoApplication.class);
addInitHooks(application); addInitHooks(application);
// SpringApplication.run(ChattoApplication.class, args); // SpringApplication.run(ChattoApplication.class, args);
application.run(args); application.run(args);
} }
@Override @Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ChattoApplication.class); return application.sources(ChattoApplication.class);
} }
static void addInitHooks(SpringApplication application) { static void addInitHooks(SpringApplication application) throws SQLException {
// TBD // TBD
// System.out.println("Hello world very loooooooooooooooooooooooooooooooooooooong string"); // System.out.println("Hello world very loooooooooooooooooooooooooooooooooooooong string");
// String url = environment.getProperty("spring.datasource.url"); // String url = environment.getProperty("spring.datasource.url");

View File

@ -12,7 +12,7 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationEn
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Component @Component
public final class RestAuthenticationEntryPoint public final class RESTAuthenticationEntryPoint
extends BasicAuthenticationEntryPoint { extends BasicAuthenticationEntryPoint {
// @Override // @Override

View File

@ -5,14 +5,19 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration @Configuration
@ -25,13 +30,15 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private MyUserDetailsService myUserDetailsService; private MyUserDetailsService myUserDetailsService;
@Autowired @Autowired
private PasswordEncoder passwordEncoder; private PasswordEncoder passwordEncoder;
@Autowired
private UserCache userCache;
// @SuppressWarnings("deprecation") // @SuppressWarnings("deprecation")
@Bean @Bean
public AuthenticationProvider authenticationProvider() { public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(myUserDetailsService); provider.setUserDetailsService(myUserDetailsService);
provider.setUserCache(userCache);
provider.setPasswordEncoder(passwordEncoder); provider.setPasswordEncoder(passwordEncoder);
return provider; return provider;
} }
@ -41,29 +48,23 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
return new BCryptPasswordEncoder(); return new BCryptPasswordEncoder();
} }
@Configuration @Configuration
@Order(1) @Order(1)
public static class ApiWebSecurity extends WebSecurityConfigurerAdapter { public static class ApiWebSecurity extends WebSecurityConfigurerAdapter {
@Autowired @Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint; private RESTAuthenticationEntryPoint authenticationEntryPoint;
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http http.csrf().disable().exceptionHandling()
.csrf().disable()
.exceptionHandling()
.and() .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// .cors().and() // .cors().and()
.antMatcher("/api/**") .antMatcher("/api/**").authorizeRequests()
.authorizeRequests()
// .antMatchers("/perform-login").permitAll() // .antMatchers("/perform-login").permitAll()
.anyRequest() .anyRequest()
// .hasAnyRole("USER", "ADMIN", "SUPER_USER") // .hasAnyRole("USER", "ADMIN", "SUPER_USER")
.authenticated() .authenticated().and().httpBasic().authenticationEntryPoint(authenticationEntryPoint)
.and().httpBasic()
.authenticationEntryPoint(restAuthenticationEntryPoint)
// .and() // .and()
// .logout().invalidateHttpSession(true).clearAuthentication(true) // .logout().invalidateHttpSession(true).clearAuthentication(true)
// .logoutRequestMatcher(new AntPathRequestMatcher("/api/perform_logout")) // .logoutRequestMatcher(new AntPathRequestMatcher("/api/perform_logout"))
@ -79,8 +80,19 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
} }
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.eraseCredentials(false);
// }
//
// public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
//
// }
} }
@Configuration @Configuration
@Order(2) @Order(2)
public static class FormWebSecurity extends WebSecurityConfigurerAdapter { public static class FormWebSecurity extends WebSecurityConfigurerAdapter {
@ -89,12 +101,12 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity httpSecurity) throws Exception { protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests() httpSecurity.authorizeRequests()
// .antMatchers(HttpMethod.POST, "/api/**").permitAll() // .antMatchers(HttpMethod.POST, "/api/**").permitAll()
.antMatchers("/", "perform_login","/login*", "/registration", "/perform_registration", "/css/**", "/js/**", .antMatchers("/", "perform_login","/logout**" ,"/favicon.ico","/login*", "/registration", "/perform_registration", "/css/**",
"/images/**") "/js/**", "/img/**")
.permitAll() .permitAll()
// .antMatchers("/","/api**","/api/**","/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("/user/**").hasAnyRole("USER", "ADMIN", "SUPER_USER").antMatchers("/admin/**")
.antMatchers("/admin/**").hasAnyRole("ADMIN", "SUPER_USER") .hasAnyRole("ADMIN", "SUPER_USER")
// .and() // .and()
// .antMatcher("/api/**") // .antMatcher("/api/**")
// .authorizeRequests() // .authorizeRequests()
@ -102,18 +114,17 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
.and() .and()
.formLogin() .formLogin().loginPage("/login").permitAll().loginProcessingUrl("/perform_login")
.loginPage("/login").permitAll()
.loginProcessingUrl("/login")
// .successHandler(authenticationSuccessHandler) // .successHandler(authenticationSuccessHandler)
// .failureUrl("/?login_error") // .failureUrl("/?login_error")
.and() // .and()
.logout().invalidateHttpSession(true).clearAuthentication(true) // .logout().invalidateHttpSession(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/perform_logout")) // .clearAuthentication(true)
// .logoutRequestMatcher(new AntPathRequestMatcher("/perform_logout"))
// .logoutSuccessUrl("/").permitAll() // .logoutSuccessUrl("/").permitAll()
// .and().httpBasic(); // .and().httpBasic();
// .and().cors() // .and().cors()
// .and().csrf().disable(); .and().csrf().disable();
; ;
// httpSecurity // httpSecurity
// .csrf().disable() // .csrf().disable()
@ -129,8 +140,18 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
// .logoutSuccessUrl("/").permitAll(); // .logoutSuccessUrl("/").permitAll();
} }
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.eraseCredentials(false);
// }
} }
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.eraseCredentials(false);
// }
// @Override // @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception { // protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.inMemoryAuthentication() // auth.inMemoryAuthentication()

View File

@ -0,0 +1,47 @@
package org.ros.chatto.config;
import org.ros.chatto.security.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.cache.SpringCacheBasedUserCache;
@EnableCaching
@Configuration
public class CacheConfig {
@Autowired
private CacheManager cacheManager;
@Bean
public UserCache userCache() throws Exception {
// return new EhCacheBasedUserCache();
// Cache cache = (Cache) cacheManager().getCache("userCache");
Cache cache = cacheManager.getCache("chatUser");
return new SpringCacheBasedUserCache(cache);
}
// private net.sf.ehcache.CacheManager cacheManager;
// @PreDestroy
// public void destroy() {
// cacheManager.shutdown();
// }
//
// @Bean
// public CacheManager cacheManager() {
//// log.debug("Starting Ehcache");
// cacheManager = net.sf.ehcache.CacheManager.create();
// cacheManager.getConfiguration().setMaxBytesLocalHeap("16M");
// EhCacheCacheManager ehCacheManager = new EhCacheCacheManager();
// ehCacheManager.setCacheManager(cacheManager);
// return ehCacheManager;
// }
}

View File

@ -0,0 +1,19 @@
package org.ros.chatto.config;
import org.ehcache.event.CacheEvent;
import org.ehcache.event.CacheEventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
//@Component
public class CustomCacheEventLogger implements CacheEventListener<Object, Object> {
private static final Logger LOG = LoggerFactory.getLogger(CustomCacheEventLogger.class);
@Override
public void onEvent(CacheEvent<? extends Object, ? extends Object> cacheEvent) {
LOG.info("custom Caching event {} key = {} old {} new {} ", cacheEvent.getType(), cacheEvent.getKey(),
cacheEvent.getOldValue(), cacheEvent.getNewValue());
}
}

View File

@ -10,6 +10,7 @@ import java.util.List;
import org.ros.chatto.dto.ChatMessageDTO; import org.ros.chatto.dto.ChatMessageDTO;
import org.ros.chatto.model.MessageCipher; import org.ros.chatto.model.MessageCipher;
import org.ros.chatto.service.ChatService; import org.ros.chatto.service.ChatService;
import org.ros.chatto.service.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -27,6 +28,9 @@ public class ChatMessageController {
@Autowired @Autowired
private ChatService chatService; private ChatService chatService;
@Autowired
private UserService userService;
@PostMapping(value = "/post/message", consumes = { "application/json" }) @PostMapping(value = "/post/message", consumes = { "application/json" })
@ResponseBody @ResponseBody
public ResponseEntity<ChatMessageDTO> newMessage(@RequestBody ChatMessageDTO chatMessageDTO, Principal principal) { public ResponseEntity<ChatMessageDTO> newMessage(@RequestBody ChatMessageDTO chatMessageDTO, Principal principal) {
@ -64,6 +68,11 @@ public class ChatMessageController {
List<ChatMessageDTO> chatMessageDTOs = chatService.getNewMessages(principal.getName(), userName, date); List<ChatMessageDTO> chatMessageDTOs = chatService.getNewMessages(principal.getName(), userName, date);
return chatMessageDTOs; return chatMessageDTOs;
} }
@GetMapping("/get/users")
public List<String> getAllOtherUsers(Principal principal)
{
return userService.findAllOtherUsers(principal.getName());
}
} }
//public ResponseEntity<List<ChatMessage>> getMessages(@PathVariable String userName, Principal principal) { //public ResponseEntity<List<ChatMessage>> getMessages(@PathVariable String userName, Principal principal) {

View File

@ -34,23 +34,27 @@ public class Home {
@Autowired @Autowired
private UserService userService; private UserService userService;
@Autowired // @Autowired
private DBInitializerService dbInitializerService; // private DBInitializerService dbInitializerService;
private boolean installationChecked = false; // private boolean installationChecked = false;
@RequestMapping("/") @RequestMapping("/")
public ModelAndView showPage(Principal principal) throws SQLException { public ModelAndView showPage(Principal principal) throws SQLException {
ModelAndView mv = new ModelAndView("home"); ModelAndView mv = new ModelAndView("home");
mv.addObject("message", "Welcome!"); String welcomeMesage = String.format("Welcome to chatto");
// mv.addObject("userNames", userService.findAllOtherUsers(principal.getName())); if (principal != null) {
if (!installationChecked) { welcomeMesage = String.format("Welcome back %s!", principal.getName());
dbInitializerService.connectDB();
if(dbInitializerService.getNumTables() == 0)
dbInitializerService.populateDB();
dbInitializerService.closeConnection();
installationChecked = true;
} }
mv.addObject("message", welcomeMesage);
// mv.addObject("userNames", userService.findAllOtherUsers(principal.getName()));
// if (!installationChecked) {
// dbInitializerService.connectDB();
// if(dbInitializerService.getNumTables() == 0)
// dbInitializerService.populateDB();
// dbInitializerService.closeConnection();
// installationChecked = true;
// }
return mv; return mv;
} }

View File

@ -45,7 +45,8 @@ public class ChatUser {
// @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) // @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL) @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
@JsonBackReference @JsonBackReference
private Set<UserRole> userRoles = new HashSet<UserRole>(); // private Set<UserRole> userRoles = new HashSet<UserRole>();
private Set<UserRole> userRoles;
public int getUserID() { public int getUserID() {
return userID; return userID;

View File

@ -11,4 +11,7 @@ import org.springframework.stereotype.Repository;
public interface UserRoleRepository extends JpaRepository<UserRole, Long>{ public interface UserRoleRepository extends JpaRepository<UserRole, Long>{
@Query("select ur from UserRole ur where ur.user.userID = ?1") @Query("select ur from UserRole ur where ur.user.userID = ?1")
public List<UserRole> findByUser(int userID); public List<UserRole> findByUser(int userID);
@Query("select ur from UserRole ur where ur.user.userName = ?1")
public List<UserRole> findByUser(String username);
} }

View File

@ -1,8 +1,11 @@
package org.ros.chatto.security; package org.ros.chatto.security;
import java.util.List; import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.validation.constraints.Size;
import org.ros.chatto.model.ChatUser; import org.ros.chatto.model.ChatUser;
import org.ros.chatto.model.UserRole; import org.ros.chatto.model.UserRole;
@ -10,7 +13,11 @@ import org.ros.chatto.repository.RoleRepository;
import org.ros.chatto.repository.UserRepository; import org.ros.chatto.repository.UserRepository;
import org.ros.chatto.repository.UserRoleRepository; import org.ros.chatto.repository.UserRoleRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.Cache.ValueWrapper;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
@ -30,6 +37,15 @@ public class MyUserDetailsService implements UserDetailsService {
@Autowired @Autowired
private UserRoleRepository userRoleRepository; private UserRoleRepository userRoleRepository;
// @Autowired
// private UserCache userCache;
@Autowired
private CacheManager cacheManager;
// @Autowired
// private UserCache userCache;
// @PostConstruct // @PostConstruct
// public void completeSetup() { // public void completeSetup() {
// userRepository = applicationContext.getBean(UserRepository.class); // userRepository = applicationContext.getBean(UserRepository.class);
@ -38,27 +54,63 @@ public class MyUserDetailsService implements UserDetailsService {
public MyUserDetailsService() { public MyUserDetailsService() {
super(); super();
} }
@Override @Override
// @Cacheable(value="chatUser")
public UserDetails loadUserByUsername(String username) { public UserDetails loadUserByUsername(String username) {
ChatUser user = userRepository.findByUserName(username); // ChatUser user = userRepository.findByUserName(username);
List<UserRole> userRoles = userRoleRepository.findByUser(username);
// @SuppressWarnings("unchecked")
// List<UserRole> userRoles = (List<UserRole>)cacheManager.getCache(username);
// if((userRoles == null)) {
// userRoles = userRoleRepository.findByUser(username);
// }
// UserDetails userDetails = (UserDetails) cacheManager.getCache(username);
// if((userDetails == null)) {
// user = userRoleRepository.findByUser(username);
// }
System.out.println("Test from userdetails");
ValueWrapper valueWrapper = cacheManager.getCache("chatUser").get("hmm");
if (user == null) { if (valueWrapper != null) {
UserDetails userDetails = (UserDetails) valueWrapper.get();
if (userDetails != null) {
System.out.println("cache username = " + userDetails.getUsername());
System.out.println("cache password = " + userDetails.getPassword());
}
}
if (userRoles.size() == 0) {
throw new UsernameNotFoundException(username); throw new UsernameNotFoundException(username);
} }
System.out.println("Found useeeeeeeeeeeeeeeeeeeeeeeeeeeeeeer " + user.getUserName() + user.getPassword()); // System.out.println("Found useeeeeeeeeeeeeeeeeeeeeeeeeeeeeeer " + user.getUserName() + user.getPassword());
List<UserRole> userRoles = userRoleRepository.findByUser(user.getUserID());
System.out.println("User role iddddddddddddddddd = " + userRoles.get(0).getRole().getName()); // ChatUser user2 = userRoles.get(0).getUser();
// System.out.println("User role iddddddddddddddddd = " + userRoles.get(0).getRole().getName());
// System.out.println(userRoles.); // System.out.println(userRoles.);
// return new MyUserPrincipal(user); // return new MyUserPrincipal(user);
return toUserDetails(new UserObject(user.getUserName(), user.getPassword(), userRoles.get(0).getRole().getName())); // return toUserDetails(new UserObject(user.getUserName(), user.getPassword(), userRoles.get(0).getRole().getName()));
// return User.withUsername(user.getUserName()).password(user.getPassword())
// .roles(
// user.getUserRoles()
// .stream()
// .map(userRole -> {
// System.out.println("role = " + userRole.getRole().getName());
// return userRole.getRole().getName();
// })
// .toArray(size -> new String[size])
// )
// .build();
ChatUser user = userRoles.get(0).getUser();
return User.withUsername(user.getUserName()).password(user.getPassword())
.roles(userRoles.stream().map(userRole -> {
System.out.println("role = " + userRole.getRole().getName());
return userRole.getRole().getName();
}).toArray(size -> new String[size])).build();
} }
private UserDetails toUserDetails(UserObject userObject) { private UserDetails toUserDetails(UserObject userObject) {
return User.withUsername(userObject.name) return User.withUsername(userObject.name).password(userObject.password).roles(userObject.role).build();
.password(userObject.password)
.roles(userObject.role).build();
} }
private static class UserObject { private static class UserObject {

View File

@ -1,14 +1,22 @@
package org.ros.chatto.service; package org.ros.chatto.service;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Properties;
import org.ros.chatto.ChattoApplication;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
import org.springframework.context.event.EventListener;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.EncodedResource; import org.springframework.core.io.support.EncodedResource;
import org.springframework.jdbc.datasource.init.ScriptUtils; import org.springframework.jdbc.datasource.init.ScriptUtils;
@ -38,6 +46,9 @@ public class DBInitializerService {
@Value("${num-tables}") @Value("${num-tables}")
private String numTablesQuery; private String numTablesQuery;
@Value("${test.bindAddress}")
private String bindAddress;
private Connection connection; private Connection connection;
// public DBInitializerService(Connection connection) { // public DBInitializerService(Connection connection) {
@ -111,7 +122,18 @@ public class DBInitializerService {
return numTables; return numTables;
} }
public void populateDB() throws SQLException { @EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() throws SQLException, IOException {
// setProperties();
System.out.println("Hello world, I have just started up");
System.out.println("Initializing database");
connectDB();
if (getNumTables() == 0)
populateDB();
closeConnection();
}
public void populateDB() throws SQLException, IOException {
// System.out.println("Database name = " + dbName); // System.out.println("Database name = " + dbName);
// String sql = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '" + dbName + "' and TABLE_TYPE='BASE TABLE' "; // String sql = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '" + dbName + "' and TABLE_TYPE='BASE TABLE' ";
// String sql = numTablesQuery; // String sql = numTablesQuery;
@ -139,6 +161,36 @@ public class DBInitializerService {
// connection.close(); // connection.close();
} }
public void setProperties() throws IOException {
// InputStream input = ChattoApplication.class.getClassLoader().getResourceAsStream("messages.properties");
OutputStream outputStream = new FileOutputStream("messages.properties");
// FileInputStream in = new FileInputStream("First.properties");
// Properties props = new Properties();
// props.load(in);
// in.close();
//
// FileOutputStream out = new FileOutputStream("First.properties");
// props.setProperty("country", "america");
// props.store(out, null);
// out.close();
Properties prop = new Properties();
System.out.println("Hello from setProperties");
prop.setProperty("test.bindAddress", bindAddress);
prop.store(outputStream, null);
// if (input == null) {
// System.out.println("Sorry, unable to find messages.properties");
// return;
// }
// load a properties file from class path, inside static method
// prop.load(input);
// Object object = prop.setProperty("test.bindAddress", bindAddress);
// input.close();
outputStream.close();
// prop.store(object, comments);
}
public void closeConnection() throws SQLException { public void closeConnection() throws SQLException {
connection.close(); connection.close();
} }

View File

@ -21,3 +21,7 @@ spring.http.log-request-details=true
#spring.jackson.date-format=yyyy-MM-d #spring.jackson.date-format=yyyy-MM-d
spring.jackson.serialization.write-dates-as-timestamps=false spring.jackson.serialization.write-dates-as-timestamps=false
#spring.mvc.static-path-pattern=/static/** #spring.mvc.static-path-pattern=/static/**
#spring.cache.type=ehcache3
spring.cache.jcache.config=classpath:ehcache.xml
logging.level.org.springframework.cache = DEBUG
#test.bindAddress=192.168.1.106

View File

@ -0,0 +1,44 @@
<config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns='http://www.ehcache.org/v3'
xmlns:jsr107='http://www.ehcache.org/v3/jsr107'>
<service>
<jsr107:defaults enable-statistics="true" />
</service>
<cache alias="chatUser">
<key-type>java.lang.String</key-type>
<value-type>org.springframework.security.core.userdetails.UserDetails</value-type>
<expiry>
<ttl unit="seconds">600</ttl>
</expiry>
<listeners>
<listener>
<class>org.ros.chatto.config.CustomCacheEventLogger</class>
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
<event-ordering-mode>UNORDERED</event-ordering-mode>
<events-to-fire-on>CREATED</events-to-fire-on>
<events-to-fire-on>UPDATED</events-to-fire-on>
<events-to-fire-on>EXPIRED</events-to-fire-on>
<events-to-fire-on>REMOVED</events-to-fire-on>
<events-to-fire-on>EVICTED</events-to-fire-on>
</listener>
</listeners>
<resources>
<heap unit="entries">2000</heap>
<offheap unit="MB">100</offheap>
</resources>
</cache>
<!-- <cache alias="user"
maxEntriesLocalHeap="10000"
maxEntriesLocalDisk="1000"
eternal="false"
diskSpoolBufferSizeMB="20"
timeToIdleSeconds="300" timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache> -->
</config>

View File

@ -0,0 +1 @@
#test.bindAddress=192.168.1.106

View File

@ -0,0 +1,322 @@
/*------------------------------------
- COLOR primary
------------------------------------*/
/*
.alert-primary {
color: #191d21;
background-color: #b8c1c9;
border-color: #adb6c0;
}
.alert-primary hr {
border-top-color: #9eaab5;
}
.alert-primary .alert-link {
color: #030404;
}
.badge-primary {
color: #fff;
background-color: #4f5b67;
}
.badge-primary[href]:hover,
.badge-primary[href]:focus {
color: #fff;
background-color: #38414a;
}
.bg-primary {
background-color: #4f5b67 !important;
}
a.bg-primary:hover,
a.bg-primary:focus,
button.bg-primary:hover,
button.bg-primary:focus {
background-color: #38414a !important;
}
.border-primary {
border-color: #4f5b67 !important;
}
.btn-primary {
color: #fff;
background-color: #4f5b67;
border-color: #4f5b67;
}
.btn-primary:hover {
color: #fff;
background-color: #3f4952;
border-color: #38414a;
}
.btn-primary:focus,
.btn-primary.focus {
box-shadow: 0 0 0 0.2rem rgba(79, 91, 103, 0.5);
}
.btn-primary.disabled,
.btn-primary:disabled {
color: #fff;
background-color: #4f5b67;
border-color: #4f5b67;
}
.btn-primary:not(:disabled):not(.disabled):active,
.btn-primary:not(:disabled):not(.disabled).active,
.show>.btn-primary.dropdown-toggle {
color: #fff;
background-color: #38414a;
border-color: #323941;
}
.btn-primary:not(:disabled):not(.disabled):active:focus,
.btn-primary:not(:disabled):not(.disabled).active:focus,
.show>.btn-primary.dropdown-toggle:focus {
box-shadow: 0 0 0 0.2rem rgba(79, 91, 103, 0.5);
}
.btn-outline-primary {
color: #4f5b67;
background-color: transparent;
border-color: #4f5b67;
}
.btn-outline-primary:hover {
color: #fff;
background-color: #4f5b67;
border-color: #4f5b67;
}
.btn-outline-primary:focus,
.btn-outline-primary.focus {
box-shadow: 0 0 0 0.2rem rgba(79, 91, 103, 0.5);
}
.btn-outline-primary.disabled,
.btn-outline-primary:disabled {
color: #4f5b67;
background-color: transparent;
}
.btn-outline-primary:not(:disabled):not(.disabled):active,
.btn-outline-primary:not(:disabled):not(.disabled).active,
.show>.btn-outline-primary.dropdown-toggle {
color: #fff;
background-color: #4f5b67;
border-color: #4f5b67;
}
.btn-outline-primary:not(:disabled):not(.disabled):active:focus,
.btn-outline-primary:not(:disabled):not(.disabled).active:focus,
.show>.btn-outline-primary.dropdown-toggle:focus {
box-shadow: 0 0 0 0.2rem rgba(79, 91, 103, 0.5);
}
.list-group-item-primary {
color: #191d21;
background-color: #adb6c0;
}
.list-group-item-primary.list-group-item-action:hover,
.list-group-item-primary.list-group-item-action:focus {
color: #191d21;
background-color: #9eaab5;
}
.list-group-item-primary.list-group-item-action.active {
color: #fff;
background-color: #191d21;
border-color: #191d21;
}
.table-primary,
.table-primary>th,
.table-primary>td {
background-color: #adb6c0;
}
.table-hover .table-primary:hover {
background-color: #9eaab5;
}
.table-hover .table-primary:hover>td,
.table-hover .table-primary:hover>th {
background-color: #9eaab5;
}
.text-primary {
color: #4f5b67 !important;
}
a.text-primary:hover,
a.text-primary:focus {
color: #38414a !important;
} */
/*------------------------------------
- COLOR primary
------------------------------------*/
.alert-primary {
color: #14171b;
background-color: #b1bbc4;
border-color: #a5b0bb;
}
.alert-primary hr {
border-top-color: #97a4b0;
}
.alert-primary .alert-link {
color: #000000;
}
.badge-primary {
color: #fff;
background-color: #495561;
}
.badge-primary[href]:hover,
.badge-primary[href]:focus {
color: #fff;
background-color: #333b43;
}
.bg-primary {
background-color: #495561 !important;
}
a.bg-primary:hover,
a.bg-primary:focus,
button.bg-primary:hover,
button.bg-primary:focus {
background-color: #333b43 !important;
}
.border-primary {
border-color: #495561 !important;
}
.btn-primary {
color: #fff;
background-color: #495561;
border-color: #495561;
}
.btn-primary:hover {
color: #fff;
background-color: #39434c;
border-color: #333b43;
}
.btn-primary:focus,
.btn-primary.focus {
box-shadow: 0 0 0 0.2rem rgba(73, 85, 97, 0.5);
}
.btn-primary.disabled,
.btn-primary:disabled {
color: #fff;
background-color: #495561;
border-color: #495561;
}
.btn-primary:not(:disabled):not(.disabled):active,
.btn-primary:not(:disabled):not(.disabled).active,
.show>.btn-primary.dropdown-toggle {
color: #fff;
background-color: #333b43;
border-color: #2c333b;
}
.btn-primary:not(:disabled):not(.disabled):active:focus,
.btn-primary:not(:disabled):not(.disabled).active:focus,
.show>.btn-primary.dropdown-toggle:focus {
box-shadow: 0 0 0 0.2rem rgba(73, 85, 97, 0.5);
}
.btn-outline-primary {
color: #495561;
background-color: transparent;
border-color: #495561;
}
.btn-outline-primary:hover {
color: #fff;
background-color: #495561;
border-color: #495561;
}
.btn-outline-primary:focus,
.btn-outline-primary.focus {
box-shadow: 0 0 0 0.2rem rgba(73, 85, 97, 0.5);
}
.btn-outline-primary.disabled,
.btn-outline-primary:disabled {
color: #495561;
background-color: transparent;
}
.btn-outline-primary:not(:disabled):not(.disabled):active,
.btn-outline-primary:not(:disabled):not(.disabled).active,
.show>.btn-outline-primary.dropdown-toggle {
color: #fff;
background-color: #495561;
border-color: #495561;
}
.btn-outline-primary:not(:disabled):not(.disabled):active:focus,
.btn-outline-primary:not(:disabled):not(.disabled).active:focus,
.show>.btn-outline-primary.dropdown-toggle:focus {
box-shadow: 0 0 0 0.2rem rgba(73, 85, 97, 0.5);
}
.list-group-item-primary {
color: #14171b;
background-color: #a5b0bb;
}
.list-group-item-primary.list-group-item-action:hover,
.list-group-item-primary.list-group-item-action:focus {
color: #14171b;
background-color: #97a4b0;
}
.list-group-item-primary.list-group-item-action.active {
color: #fff;
background-color: #14171b;
border-color: #14171b;
}
.table-primary,
.table-primary>th,
.table-primary>td {
background-color: #a5b0bb;
}
.table-hover .table-primary:hover {
background-color: #97a4b0;
}
.table-hover .table-primary:hover>td,
.table-hover .table-primary:hover>th {
background-color: #97a4b0;
}
.text-primary {
color: #495561 !important;
}
a.text-primary:hover,
a.text-primary:focus {
color: #333b43 !important;
}

View File

@ -1,24 +1,126 @@
.myClass { /* .myClass {
color: red; color: red;
} */
/* https://arcusiridis.com/images/background.jpg */
body {
background: #333;
color: #ffffff;
/* background-image: url('https://bluestnight.com/images/background_lg.jpg'); */
} }
#body-container {
/* #body-container {
margin: 0 auto 0 auto; margin: 0 auto 0 auto;
max-width: 80%; max-width: 80%;
/* vertical-align: auto; */ vertical-align: auto;
} }
.shadow-sm { */
width: 50%;
} input[type="radio"] {
input[type="radio"]{
/*position:fixed;*/ /*position:fixed;*/
opacity:0; opacity: 0;
} }
input[type=radio]+label { input[type=radio]+label {
font-weight: normal; font-weight: normal;
} }
input[type=radio]:checked+label { input[type=radio]:checked+label {
font-weight: bold; font-weight: bold;
background-color: #566069;
} }
input[type=radio]:focus+label { input[type=radio]:focus+label {
border: 1px dotted #000; border: 1px dotted #000;
} }
#home-section {
background-image: url('../img/home.jpg');
background-repeat: no-repeat;
background-size: cover;
background-attachment: fixed;
min-height: 900px;
height: auto;
}
#home-section .home-inner {
padding-top: 75px;
/* padding-bottom: 10px; */
/* background: #333; */
}
/* #home-section .card-form {
opacity: 0.8;
} */
#home-section .dark-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
min-height: 900px;
background: rgba(0, 0, 0, 0.7);
}
#chat-section {
/* background-image: url('../img/home.jpg'); */
background: #495561;
/* background-repeat: no-repeat;
background-size: cover;
background-attachment: fixed; */
min-height: 500px;
}
#chat-section .chat-inner {
padding-top: 75px;
/* background: #333; */
}
#chat-section .dark-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
min-height: 600px;
/* background: rgba(0, 0, 0, 0.7); */
}
textarea {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
}
#chatTextArea {
min-height: 300px;
}
/* .container {
width: 50%;
} */
.my-form-inputs {
width: 80%;
}
#login-card {
width: 40%;
/* margin: 0 auto; */
/* Added */
/* float: none; */
/* Added */
/* margin-bottom: 10px; */
/* Added */
}
@media only screen and (max-width: 600px) {
#login-card {
width: 90%;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

View File

@ -14,14 +14,19 @@ if(!ischecked_method) { //payment method button is not checked
var toUserRadios = document.getElementsByName('toUser'); var toUserRadios = document.getElementsByName('toUser');
var isCheckedUser = false; var isCheckedUser = false;
var chatTextArea = document.getElementById('chatTextArea'); var chatTextArea = document.getElementById('chatTextArea');
var passphraseInput = document.getElementById('passphrase'); var passphraseInput = document.getElementById('passphrase');
var postNewMessageUrl = "http://localhost:8080/api/chat/post/message"; var postNewMessageUrl = `http://${hostAddress}/api/chat/post/message`; //hostAddress variable is set in the thymeleaf head fragment
var getAllMessagesUrl = "http://localhost:8080/api/chat/get/messages/"; var getAllMessagesUrl = `http://${hostAddress}/api/chat/get/messages/`;
var getNewMessagesUrl = "http://localhost:8080/api/chat/get/messages/"; var getNewMessagesUrl = `http://${hostAddress}/api/chat/get/messages/`;
// var postNewMessageUrl = "http://localhost:8080/api/chat/post/message";
// var getAllMessagesUrl = "http://localhost:8080/api/chat/get/messages/";
// var getNewMessagesUrl = "http://localhost:8080/api/chat/get/messages/";
// var messageLog = []; // var messageLog = [];
var username = sessionStorage.getItem('username'); var username = sessionStorage.getItem('username');
var password = sessionStorage.getItem('password'); var password = sessionStorage.getItem('password');
var authToken = 'Basic ' + btoa(username + ":" + password); var authToken = 'Basic ' + btoa(username + ":" + password);
var iterations = 100000;
// var lastMessageTimeStamp; // var lastMessageTimeStamp;
// console.log(authToken); // console.log(authToken);
@ -60,8 +65,9 @@ function handleChatForm() {
let localDate = new Date(); let localDate = new Date();
let messageLine = sprintf('%s %s %s: %s', localDate.toLocaleDateString(), localDate.toLocaleTimeString(), username, messageContent); let messageLine = sprintf('%s %s %s: %s', localDate.toLocaleDateString(), localDate.toLocaleTimeString(), username, messageContent);
chatTextArea.append(messageLine + "\n"); chatTextArea.append(messageLine + "\n");
chatTextArea.scrollTop = chatTextArea.scrollHeight;
// let messageCipher = sjcl.encrypt("password", messageContent); // let messageCipher = sjcl.encrypt("password", messageContent);
let messageCipher = sjcl.encrypt(passphraseInput.value, messageContent); let messageCipher = sjcl.encrypt(passphraseInput.value, messageContent,{mode: "gcm",ts: 128, adata: "",iter: iterations});
let messageCipherJson = JSON.parse(messageCipher); let messageCipherJson = JSON.parse(messageCipher);
// let messageCipherSpring = JSON.stringify(messageCipherJson); // let messageCipherSpring = JSON.stringify(messageCipherJson);
// console.log('message cipher json ' + messageCipherJson); // console.log('message cipher json ' + messageCipherJson);
@ -76,6 +82,7 @@ function handleChatForm() {
// sessionStorage.setItem('passphrase', passphraseInput.value); // sessionStorage.setItem('passphrase', passphraseInput.value);
// console.log(sessionStorage.getItem('passphrase')); // console.log(sessionStorage.getItem('passphrase'));
}) })
} }
@ -215,6 +222,7 @@ parent.addDelegatedListener("click", "input[type='radio']", function (event) {
// chatTextArea.append(obj.fromUser + ": " + message + "\n"); // chatTextArea.append(obj.fromUser + ": " + message + "\n");
chatTextArea.append(messageLine + '\n'); chatTextArea.append(messageLine + '\n');
messageLog[i++] = messageLine; messageLog[i++] = messageLine;
chatTextArea.scrollTop = chatTextArea.scrollHeight;
// console.log('Message log = ' + messageLog); // console.log('Message log = ' + messageLog);
@ -255,7 +263,7 @@ parent.addDelegatedListener("click", "input[type='radio']", function (event) {
console.log(messageLine); console.log(messageLine);
// chatTextArea.append(obj.fromUser + ": " + message + "\n"); // chatTextArea.append(obj.fromUser + ": " + message + "\n");
chatTextArea.append(messageLine + '\n'); chatTextArea.append(messageLine + '\n');
chatTextArea.scrollTop = chatTextArea.scrollHeight;
storedMessages.push(messageLine); storedMessages.push(messageLine);
}) })
@ -264,12 +272,15 @@ parent.addDelegatedListener("click", "input[type='radio']", function (event) {
console.log("this value stored" + sessionStorage.getItem(this.value)) console.log("this value stored" + sessionStorage.getItem(this.value))
console.log("last message time stamp = " + lastMessageTimeStamp); console.log("last message time stamp = " + lastMessageTimeStamp);
console.log(sessionStorage.getItem(this.value + '-time')); console.log(sessionStorage.getItem(this.value + '-time'));
}
chatTextArea.textContent = ''; chatTextArea.textContent = '';
console.log("Stored messages 2 = " + storedMessages); console.log("Stored messages 2 = " + storedMessages);
storedMessages.forEach(function (messageLine) { storedMessages.forEach(function (messageLine) {
chatTextArea.append(messageLine + '\n'); chatTextArea.append(messageLine + '\n');
chatTextArea.scrollTop = chatTextArea.scrollHeight;
}) })
}
}); });

View File

@ -0,0 +1,22 @@
var chatTextArea = document.getElementById('chatTextArea');
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 = localDate.toLocaleDateString() + localDate.toLocaleTimeString() + 'fromUser' + ': ' + messageContent;
chatTextArea.append(messageLine + "\n");
chatTextArea.scrollTop = chatTextArea.scrollHeight;
})
}
handleChatForm();

View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<div th:replace="fragments/head :: headFragment">
<meta charset="UTF-8">
<title id="pageTitle">Home</title>
</div>
<script src="https://code.jquery.com/jquery-2.1.4.min.js" th:if="false"></script>
<script src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js" defer="defer"
th:if="false"></script>
<meta charset="UTF-8">
<title></title>
</head>
<body>
</body>
</html>

View File

@ -2,37 +2,104 @@
<html xmlns:th="http://www.thymeleaf.org"> <html xmlns:th="http://www.thymeleaf.org">
<head> <head>
<script src="https://code.jquery.com/jquery-2.1.4.min.js" th:if="false"></script>
<script src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js" defer="defer" th:if="false"></script>
<div th:replace="fragments/head :: headFragment"> <div th:replace="fragments/head :: headFragment">
<meta charset="UTF-8"> <meta charset="UTF-8">
<title id="pageTitle">Chat</title> <title id="pageTitle">Chat</title>
</div> </div>
<!-- <script th:src="@{js/my_Crypto.js}" type="text/javascript"></script> --> <!-- <script th:src="@{js/my_Crypto.js}" type="text/javascript"></script> -->
<link th:href="@{/css/master.css}" href="../static/css/master.css" rel="stylesheet">
</link>
</head> </head>
<body> <body>
<textarea id="chatTextArea" cols="80" rows="20" disabled></textarea> <div th:include="fragments/navbar :: navbarFragment"></div>
<header id="chat-section">
<div class="dark-overlay">
<div class="chat-inner container bg-primary">
<div class="row">
<div class="col-sm d-lg-block">
<h1 class="display-4">Chat with your friends</h1>
<div class="d-flex">
<div class="p-4 align-self-start">
</div>
<div class="p-4 align-self-end">
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Laboriosam dolorem nostrum consequatur eos voluptates. Ipsam ullam quos illo qui. Quaerat corrupti nisi numquam rerum quasi nesciunt deserunt fugit commodi consequatur!
</div>
</div>
</div>
</div>
</div>
</div>
</header>
<section>
<div class="container">
<div class="row">
<div class="col-sm">
<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">
<div class="card-body rounded">
<!-- <h4 class="card-title">Chat</h4> -->
<div class="form-group">
<textarea id="chatTextArea" class="form-control-lg py-2" disabled></textarea>
</div>
<!-- <form action="#" th:action="@{/seedstartermng}" th:object="${seedStarter}" method="post"> --> <!-- <form action="#" th:action="@{/seedstartermng}" th:object="${seedStarter}" method="post"> -->
<!-- th:action="@{/api/chat}" --> <!-- th:action="@{/api/chat}" -->
<div class="card-text">
</div>
<form action="#" th:object="${chatMessageDTO}" method="post" id="chatMessageForm"> <form action="#" th:object="${chatMessageDTO}" method="post" id="chatMessageForm">
<label for="toUser">User to send to: </label> <div class="row">
<div class="col-3">
<div class="form-group">
<label class="lead" for="toUser">User to send to: </label>
<th:block th:each="userName: ${userNames}"> <th:block th:each="userName: ${userNames}">
<input type="radio" th:field="*{toUser}" th:value="${userName}"> <input class="form-control" type="radio" th:field="*{toUser}" th:value="${userName}">
<label th:for="${#ids.prev('toUser')}" th:text="${userName}">DemoUser</label> <label class="btn btn-secondary" th:for="${#ids.prev('toUser')}" th:text="${userName}">
</th:block> <br> Demo User
</label>
</th:block>
</div>
</div>
<div class="col">
<div class="my-form-inputs container">
<div class="form-group">
<label for="chatInput">Your message: </label> <label for="chatInput">Your message: </label>
<input type="text" id="chatInput"> <br> <textarea class="form-control" type="text" id="chatInput"></textarea>
</div>
<div class="form-group">
<label for="passphrase">Passphrase: </label> <label for="passphrase">Passphrase: </label>
<input type="password" id="passphrase"> <input class="form-control" type="password" id="passphrase">
<input type="submit" value="Send"> </div>
<div class="form-group">
<input class="form-control btn btn-secondary" type="submit" value="Send">
</div>
</div>
</div>
</div>
</form> </form>
</div>
</div>
</div>
</div>
</div>
</section>
</body> </body>
<script th:src="@{js/chat.js}" type="text/javascript"></script> <script th:src="@{js/chat.js}" type="text/javascript"></script>
<script src="../static/js/chatStatic.js" th:if="false"></script>
</html> </html>
<!-- <div th:include="::frag (${value1},${value2})">...</div> <!-- <div th:include="::frag (${value1},${value2})">...</div>

View File

@ -5,10 +5,24 @@
<th:block th:fragment="headFragment"> <th:block th:fragment="headFragment">
<script th:src="@{js/scljs.js}" type="text/javascript"></script> <script th:src="@{js/scljs.js}" type="text/javascript"></script>
<!--<script th:src="@{js/my_Crypto.js}" type="text/javascript"></script>--> <!--<script th:src="@{js/my_Crypto.js}" type="text/javascript"></script>-->
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.css" rel="stylesheet"
type="text/css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/sprintf/1.1.2/sprintf.min.js" type="text/javascript"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/sprintf/1.1.2/sprintf.min.js" type="text/javascript"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.15.0/esm/popper.js" type="module"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">
<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);
</script>
<meta charset="UTF-8"> <meta charset="UTF-8">
<!-- <title th:text="${title}">Page</title> --> <!-- <title th:text="${title}">Page</title> -->
<title th:include=":: #pageTitle">Layout Generic Title</title> <title th:include=":: #pageTitle">Layout Generic Title</title>

View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="fragments/head :: headFragment">
<meta charset="UTF-8">
<title id="pageTitle">Navbar Fragment</title>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.15.0/esm/popper.js" type="module" th:if="false"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.css" th:if="false" rel="stylesheet" type="text/css">
<script src="https://code.jquery.com/jquery-2.1.4.min.js" th:if="false"></script>
<script src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js" defer="defer" th:if="false"></script>
</head>
<body>
<th:block th:fragment="navbarFragment">
<!-- <div class="container"> -->
<nav class="navbar navbar-expand-sm bg-dark navbar-dark fixed-top">
<div class="container">
<a href="home.html" th:href="@{/}" class="navbar-brand">Chatto</a>
<div class="navbar-header">
<button class="navbar-toggler" data-toggle="collapse" data-target="#navbarCollapse">
<!-- <span class="navbar-toggle-icon">Menu</span> -->
<!-- Menu -->
<!-- <i class="fas fa-angle-double-up"></i> -->
<!-- <i class="glyphicon glyphicon-align-left"></i> -->
<i class="fas fa-chevron-down"></i>
</button>
</div>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a href="home.html" th:href="@{/}" class="nav-link">Home</a>
</li>
<li class="nav-item">
<a href="user/home.html" th:href="@{/user}" class="nav-link">User Area</a>
</li>
<li class="nav-item">
<a th:href="chat" href="chat.html" class="nav-link">Chat</a>
</li>
<li class="nav-item">
<a th:href="login" href="login.html" class="nav-link">Login</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">About</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">Contact</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- </div> -->
</th:block>
</body>
</html>

View File

@ -1,19 +1,107 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org"> <html xmlns:th="http://www.thymeleaf.org">
<head> <head>
<title>Title</title> <div th:replace="fragments/head :: headFragment">
</head> <meta charset="UTF-8">
<body> <title id="pageTitle">Home</title>
<div>
Web Application. Passed parameter : <span th:text="${message}"></span>
</div> </div>
<!-- <script th:src="@{js/my_Crypto.js}" type="text/javascript"></script> -->
<script src="https://code.jquery.com/jquery-2.1.4.min.js" th:if="false"></script>
<script src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js" defer="defer" th:if="false"></script>
</link>
</head>
<body>
<div th:include="fragments/navbar :: navbarFragment"></div>
<header id="home-section">
<div class="dark-overlay">
<div class="home-inner container">
<div class="row">
<div class="col-lg-8 col-md-6 d-lg-block ">
<!-- <div class="jumbotron bg-primary"> -->
<div class="d-flex rounded">
<div class="p-4 align-self-end">
<h1 class="display-4">Chatto - Self Hosted, Minimal E2E Chat</h1>
<!-- <p th:if="${chatUser}" th:text="'username: ' + ${chatUser.userName}">You need to login</p> <!-- <p th:if="${chatUser}" th:text="'username: ' + ${chatUser.userName}">You need to login</p>
<th:block th:each="userName: ${userNames}"> <th:block th:each="userName: ${userNames}">
<div th:text="${userName}"></div> <div th:text="${userName}"></div>
</th:block> --> </th:block> -->
<p>Welcome to home page. Please login to access any features.</p> <span th:if="${message}"> Welcome <span th:text="${message}"></span></span>
<a href="login">login</a> <p>Chatto is a minimal, end to end encrypted chat application.</p>
<!-- <button class="btn btn-secondary"> <a href="registration.html" th:href="{@/registration}">Get Started</a></button> -->
<a class="btn btn-secondary" href="registration.html" th:href="@{/registration}">Get Started</a>
</div>
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="card bg-primary text-justified">
<h2 class="card-header text-center">Features</h2>
<div class="card-body ">
<p class="card-text lead">
<ul class="">
<li>
<p class="lead">
<!-- <i class="fas fa-check"></i> -->
Self Hosted</p>
</li>
<li>
<p class="lead">
<!-- <i class="fas fa-check"></i> -->
End To End Encrypted Messaging</p>
</li>
<li>
<p class="lead">
<!-- <i class="fas fa-check"></i> -->
Free Software (AGPLv3 Licensed)</p>
</li>
<li>
<p class="lead">
<!-- <i class="fas fa-check"></i> -->
Built With Java And Spring</p>
</li>
</ul>
</p>
<!-- <p class="card-text">
Open Source
</p>
<p class="card-text">
Built with Java
</p> -->
</div>
</div>
</div>
</div>
</div>
</div>
</header>
<section id="my-section">
<div class="container">
<div class="row">
<div class="col text-center py-5">
<h1 class="display-4">
<p class="lead">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Aliquid illum ea accusamus animi voluptate. Quam temporibus aperiam, similique in labore sint quasi harum. Praesentium enim iste dicta quaerat perspiciatis eos.</p>
</h1>
<a href="#" class="btn btn-secondary">Find out more</a>
</div>
</div>
</div>
</section>
<script>
console.log(hostAddress);
/* console.log(hostAddress2); */
</script>
</body> </body>
</html> </html>

View File

@ -5,20 +5,96 @@
<div th:replace="fragments/head :: headFragment"> <div th:replace="fragments/head :: headFragment">
<title id="pageTitle">Login</title> <title id="pageTitle">Login</title>
</div> </div>
<script src="https://code.jquery.com/jquery-2.1.4.min.js" th:if="false"></script>
<script src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js" defer="defer" th:if="false"></script>
</head> </head>
<body> <body>
<div id="body-container" class="shadow-sm p-3 mb-5 bg-white rounded"> <div th:include="fragments/navbar :: navbarFragment"></div>
<!-- <div>Login Page</div> --> <!-- <header id="chat-section" class="bg-secondary">
<form action="#" th:action="@{/login}" method="POST" id="loginForm"> <div class="dark-overlay">
<fieldset> <div class="chat-inner container">
<!-- <form action="#" th:action="@{/greeting}" th:object="${greeting}" method="post"> <div class="row">
<div class="col-sm d-lg-block">
<h1 class="display-4">Chat with your friends</h1>
<div class="d-flex">
<div class="p-4 align-self-start">
</div>
<div class="p-4 align-self-end">
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Laboriosam dolorem nostrum consequatur eos voluptates. Ipsam ullam quos illo qui. Quaerat corrupti nisi numquam rerum quasi nesciunt deserunt fugit commodi consequatur!
</div>
</div>
</div>
</div>
</div>
</div>
</header> -->
<header>
<div class="container">
<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-body rounded">
<!-- <h4 class="card-title">Chat</h4> -->
<!-- <div class="form-group">
<textarea id="chatTextArea" class="form-control-lg py-2" disabled></textarea>
</div> -->
<!-- <form action="#" th:action="@{/seedstartermng}" th:object="${seedStarter}" method="post"> -->
<!-- th:action="@{/api/chat}" -->
<div class="card-text">
<form action="#" th:action="@{/perform_login}" method="POST" id="loginForm">
<!-- <fieldset>
<legend>Please Sign In</legend> -->
<h2 class="card-title">Please Sign In</h2>
<div th:if="${param.error}" class="alert alert-danger">
Invalid username or password.
</div>
<div th:if="${param.logout}" class="alert alert-success">
You have been logged out.
</div>
<div class="form-group">
<label for="username">Enter user name: </label>
<input class="form-control" type="text" name="username" id="username">
</div>
<div class="form-group">
<label for="password">Enter password: </label>
<input class="form-control" type="password" name="password" id="password">
</div>
<div class="form-group">
<button class="form-control btn btn-secondary" type="submit">Login</button>
</div>
<!-- </fieldset> -->
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</header>
<script src="../js/loginPage.js" type="text/javascript"></script>
</body>
</html>
<!-- form th:action="@{/login.html}" method="post" -->
<!-- <form action="#" th:action="@{/greeting}" th:object="${greeting}" method="post">
<p>Id: <input type="text" th:field="*{id}" /></p> <p>Id: <input type="text" th:field="*{id}" /></p>
<p>Message: <input type="text" th:field="*{content}" /></p> <p>Message: <input type="text" th:field="*{content}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p> <p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form> --> </form> -->
<!-- <form action="#" th:action="@{/perform_login}" th:object=${user} method="POST"> <!-- <form action="#" th:action="@{/perform_login}" th:object=${user} method="POST">
<label>Enter user name: </label> <label>Enter user name: </label>
<input th:field="*{userName}" type="text" name="username" id="username"> <input th:field="*{userName}" type="text" name="username" id="username">
<br> <br> <label>Enter password: </label> <br> <br> <label>Enter password: </label>
@ -26,26 +102,3 @@
<input type="submit" value="Submit"> <input type="submit" value="Submit">
</form> </form>
--> -->
<legend>Please Login</legend>
<div th:if="${param.error}" class="alert alert-error">
Invalid username or password.
</div>
<div th:if="${param.logout}" class="alert alert-success">
You have been logged out.
</div>
<label for="username">Enter user name: </label>
<input type="text" name="username" id="username">
<br> <br>
<label for="password">Enter password: </label>
<input type="password" name="password" id="password">
<br> <br>
<button type="submit" class="btn btn-primary">Login</button>
</fieldset>
</form>
</div>
<script src="../js/loginPage.js" type="text/javascript"></script>
</body>
</html>

View File

@ -1,13 +1,58 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"> <html xmlns:th="http://www.thymeleaf.org">
<head> <head>
<meta charset="UTF-8"> <div th:replace="fragments/head :: headFragment">
<title>Insert title here</title> <title id="pageTitle">User Home</title>
</div>
<script src="https://code.jquery.com/jquery-2.1.4.min.js" th:if="false"></script>
<script
src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js"
data-template-prefix="../" defer="defer" th:if="false"></script>
<link th:href="@{/css/master.css}" href="../../static/css/master.css"
rel="stylesheet" th:if="false">
<link th:href="@{/css/colors.css}" href="../../static/css/colors.css"
rel="stylesheet" th:if="false">
</head> </head>
<body> <body>
user page <div th:include="fragments/navbar :: navbarFragment"></div>
<form action="#" th:action="@{/perform_logout}" method="POST">
<input type="submit" value="logout"> <header>
<div class="container ">
<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">
<h1 class="display-4">User Page</h1>
<div class="card-body rounded">
<!-- <h4 class="card-title">Chat</h4> -->
<!-- <div class="form-group">
<textarea id="chatTextArea" class="form-control-lg py-2" disabled></textarea>
</div> -->
<!-- <form action="#" th:action="@{/seedstartermng}" th:object="${seedStarter}" method="post"> -->
<!-- th:action="@{/api/chat}" -->
<div class="card-text">
<div class="form-group">
<form action="#" th:action="@{/logout}" method="POST">
<!-- <input type="submit" value="logout"> -->
<!-- <input type="hidden" th:name="${_csrf.parameterName}"
th:value="${_csrf.token}" /> -->
<button class="btn btn-secondary form-control">Logout</button>
</form> </form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</header>
</body> </body>
</html> </html>