diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml new file mode 100644 index 00000000..64c7c44d --- /dev/null +++ b/.github/workflows/label.yml @@ -0,0 +1,22 @@ +# This workflow will triage pull requests and apply a label based on the +# paths that are modified in the pull request. +# +# To use this workflow, you will need to set up a .github/labeler.yml +# file with configuration. For more information, see: +# https://github.com/actions/labeler + +name: Labeler +on: [pull_request_target] + +jobs: + label: + + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + + steps: + - uses: actions/labeler@v5.0.0 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/JtProject/.classpath b/JtProject/.classpath index 65f270a0..f7196554 100644 --- a/JtProject/.classpath +++ b/JtProject/.classpath @@ -1,24 +1,11 @@ - - - - - - - - - - - - - @@ -31,19 +18,32 @@ - + + - + + + + + + + + + + + + + diff --git a/JtProject/.project b/JtProject/.project index c235c735..a9a40961 100644 --- a/JtProject/.project +++ b/JtProject/.project @@ -15,6 +15,11 @@ + + org.eclipse.buildship.core.gradleprojectbuilder + + + org.eclipse.m2e.core.maven2Builder @@ -24,6 +29,7 @@ org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature + org.eclipse.buildship.core.gradleprojectnature diff --git a/JtProject/basedata.sql b/JtProject/basedata.sql index db4e69e1..bfced167 100644 --- a/JtProject/basedata.sql +++ b/JtProject/basedata.sql @@ -1,5 +1,5 @@ # SQL configs -SET SQL_MODE ='IGNORE_SPACE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; +SET SQL_MODE ='IGNORE_SPACE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; # create database and use it CREATE DATABASE IF NOT EXISTS ecommjava; diff --git a/JtProject/pom.xml b/JtProject/pom.xml index e1f61d6a..a1de54c0 100644 --- a/JtProject/pom.xml +++ b/JtProject/pom.xml @@ -57,7 +57,11 @@ mysql-connector-java 8.0.33 - + + + org.springframework.boot + spring-boot-starter-security + @@ -70,4 +74,4 @@ - + \ No newline at end of file diff --git a/JtProject/src/main/java/com/jtspringproject/JtSpringProject/configuration/SecurityConfiguration.java b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/configuration/SecurityConfiguration.java new file mode 100644 index 00000000..8689a569 --- /dev/null +++ b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/configuration/SecurityConfiguration.java @@ -0,0 +1,111 @@ +package com.jtspringproject.JtSpringProject.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import com.jtspringproject.JtSpringProject.models.User; +import com.jtspringproject.JtSpringProject.services.userService; + +@Configuration +public class SecurityConfiguration { + + userService UserService; + + public SecurityConfiguration(userService UserService) { + this.UserService = UserService; + } + + @Configuration + @Order(1) + public static class AdminConfigurationAdapter{ + + @Bean + SecurityFilterChain adminFilterChain(HttpSecurity http) throws Exception { + http.antMatcher("/admin/**") + .authorizeHttpRequests(requests -> requests + .requestMatchers(new AntPathRequestMatcher("/admin/login")).permitAll() + .requestMatchers(new AntPathRequestMatcher("/admin/**")).hasRole("ADMIN") + ) + .formLogin(login -> login + .loginPage("/admin/login") + .loginProcessingUrl("/admin/loginvalidate") + .successHandler((request, response, authentication) -> { + response.sendRedirect("/admin/"); // Redirect on success + }) + .failureHandler((request, response, exception) -> { + response.sendRedirect("/admin/login?error=true"); // Redirect on failure + })) + + .logout(logout -> logout.logoutUrl("/admin/logout") + .logoutSuccessUrl("/admin/login") + .deleteCookies("JSESSIONID")) + .exceptionHandling(exception -> exception + .accessDeniedPage("/403") // Custom 403 page + ); + http.csrf(csrf -> csrf.disable()); + return http.build(); + } + } + + @Configuration + @Order(2) + public static class UserConfigurationAdapter{ + + @Bean + SecurityFilterChain userFilterChain(HttpSecurity http) throws Exception { + http.authorizeHttpRequests(requests -> requests + .antMatchers("/login", "/register", "/newuserregister" ,"/test", "/test2").permitAll() + .antMatchers("/**").hasRole("USER")) + .formLogin(login -> login + .loginPage("/login") + .loginProcessingUrl("/userloginvalidate") + .successHandler((request, response, authentication) -> { + response.sendRedirect("/"); // Redirect on success + }) + .failureHandler((request, response, exception) -> { + response.sendRedirect("/login?error=true"); // Redirect on failure + })) + + .logout(logout -> logout.logoutUrl("/logout") + .logoutSuccessUrl("/login") + .deleteCookies("JSESSIONID")) + .exceptionHandling(exception -> exception + .accessDeniedPage("/403") // Custom 403 page + ); + + http.csrf(csrf -> csrf.disable()); + return http.build(); + } + } + + @Bean + UserDetailsService userDetailsService() { + return username -> { + User user = UserService.getUserByUsername(username); + if(user == null) { + throw new UsernameNotFoundException("User with username " + username + " not found."); + } + String role = user.getRole().equals("ROLE_ADMIN") ? "ADMIN":"USER"; + + return org.springframework.security.core.userdetails.User + .withUsername(username) + .passwordEncoder(input->passwordEncoder().encode(input)) + .password(user.getPassword()) + .roles(role) + .build(); + }; + } + + @Bean + PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/JtProject/src/main/java/com/jtspringproject/JtSpringProject/controller/AdminController.java b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/controller/AdminController.java index 825bee35..fd2c46a3 100644 --- a/JtProject/src/main/java/com/jtspringproject/JtSpringProject/controller/AdminController.java +++ b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/controller/AdminController.java @@ -1,16 +1,23 @@ package com.jtspringproject.JtSpringProject.controller; -import java.sql.*; +import java.sql.Connection; +import java.sql.DriverManager; import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.util.List; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.*; +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.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import com.jtspringproject.JtSpringProject.models.Category; @@ -19,94 +26,55 @@ import com.jtspringproject.JtSpringProject.services.categoryService; import com.jtspringproject.JtSpringProject.services.productService; import com.jtspringproject.JtSpringProject.services.userService; -import com.mysql.cj.protocol.Resultset; - -import net.bytebuddy.asm.Advice.This; -import net.bytebuddy.asm.Advice.OffsetMapping.ForOrigin.Renderer.ForReturnTypeName; @Controller @RequestMapping("/admin") public class AdminController { - - @Autowired - private userService userService; - @Autowired - private categoryService categoryService; - + + private final userService userService; + private final categoryService categoryService; + private final productService productService; + @Autowired - private productService productService; - - int adminlogcheck = 0; - String usernameforclass = ""; - @RequestMapping(value = {"/","/logout"}) - public String returnIndex() { - adminlogcheck =0; - usernameforclass = ""; - return "userLogin"; + public AdminController(userService userService, categoryService categoryService, productService productService) { + this.userService = userService; + this.categoryService = categoryService; + this.productService = productService; } - - @GetMapping("/index") public String index(Model model) { - if(usernameforclass.equalsIgnoreCase("")) - return "userLogin"; - else { - model.addAttribute("username", usernameforclass); - return "index"; - } - + String username = SecurityContextHolder.getContext().getAuthentication().getName(); + model.addAttribute("username", username); + return "index"; } - @GetMapping("login") - public String adminlogin() { - - return "adminlogin"; - } - @GetMapping("Dashboard") - public String adminHome(Model model) { - if(adminlogcheck==1) - return "adminHome"; - else - return "redirect:/admin/login"; + public ModelAndView adminlogin(@RequestParam(required = false) String error) { + ModelAndView mv = new ModelAndView("adminlogin"); + if ("true".equals(error)) { + mv.addObject("msg", "Invalid username or password. Please try again."); + } + return mv; } - @GetMapping("/loginvalidate") - public String adminlog(Model model) { - - return "adminlogin"; - } - @RequestMapping(value = "loginvalidate", method = RequestMethod.POST) - public ModelAndView adminlogin( @RequestParam("username") String username, @RequestParam("password") String pass) { - - User user=this.userService.checkLogin(username, pass); - - if(user.getRole() != null && user.getRole().equals("ROLE_ADMIN")) { - ModelAndView mv = new ModelAndView("adminHome"); - adminlogcheck=1; - mv.addObject("admin", user); - return mv; - } - else { - ModelAndView mv = new ModelAndView("adminlogin"); - mv.addObject("msg", "Please enter correct username and password"); - return mv; - } + + @GetMapping( value={"/","Dashboard"}) + public ModelAndView adminHome(Model model) { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + ModelAndView mv = new ModelAndView("adminHome"); + mv.addObject("admin", authentication.getName()); + return mv; } + @GetMapping("categories") public ModelAndView getcategory() { - if(adminlogcheck==0){ - ModelAndView mView = new ModelAndView("adminlogin"); - return mView; - } - else { - ModelAndView mView = new ModelAndView("categories"); - List categories = this.categoryService.getCategories(); - mView.addObject("categories", categories); - return mView; - } + ModelAndView mView = new ModelAndView("categories"); + List categories = this.categoryService.getCategories(); + mView.addObject("categories", categories); + return mView; } - @RequestMapping(value = "categories",method = RequestMethod.POST) + + @PostMapping("/categories") public String addCategory(@RequestParam("categoryname") String category_name) { System.out.println(category_name); @@ -120,11 +88,10 @@ public String addCategory(@RequestParam("categoryname") String category_name) } @GetMapping("categories/delete") - public ModelAndView removeCategoryDb(@RequestParam("id") int id) + public String removeCategoryDb(@RequestParam("id") int id) { this.categoryService.deleteCategory(id); - ModelAndView mView = new ModelAndView("forward:/categories"); - return mView; + return "redirect:/admin/categories"; } @GetMapping("categories/update") @@ -138,24 +105,18 @@ public String updateCategory(@RequestParam("categoryid") int id, @RequestParam(" // --------------------------Remaining -------------------- @GetMapping("products") public ModelAndView getproduct() { - if(adminlogcheck==0){ - ModelAndView mView = new ModelAndView("adminlogin"); - return mView; - } - else { - ModelAndView mView = new ModelAndView("products"); - - List products = this.productService.getProducts(); + ModelAndView mView = new ModelAndView("products"); - if (products.isEmpty()) { - mView.addObject("msg", "No products are available"); - } else { - mView.addObject("products", products); - } - return mView; + List products = this.productService.getProducts(); + + if (products.isEmpty()) { + mView.addObject("msg", "No products are available"); + } else { + mView.addObject("products", products); } - + return mView; } + @GetMapping("products/add") public ModelAndView addProduct() { ModelAndView mView = new ModelAndView("productsAdd"); @@ -215,16 +176,10 @@ public String postproduct() { @GetMapping("customers") public ModelAndView getCustomerDetail() { - if(adminlogcheck==0){ - ModelAndView mView = new ModelAndView("adminlogin"); - return mView; - } - else { - ModelAndView mView = new ModelAndView("displayCustomers"); - List users = this.userService.getUsers(); - mView.addObject("customers", users); - return mView; - } + ModelAndView mView = new ModelAndView("displayCustomers"); + List users = this.userService.getUsers(); + mView.addObject("customers", users); + return mView; } @@ -236,7 +191,10 @@ public String profileDisplay(Model model) { Class.forName("com.mysql.jdbc.Driver"); Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/ecommjava","root",""); PreparedStatement stmt = con.prepareStatement("select * from users where username = ?"+";"); - stmt.setString(1, usernameforclass); + + String username = SecurityContextHolder.getContext().getAuthentication().getName(); + stmt.setString(1, username); + ResultSet rst = stmt.executeQuery(); if(rst.next()) @@ -277,13 +235,19 @@ public String updateUserProfile(@RequestParam("userid") int userid,@RequestParam pst.setString(4, address); pst.setInt(5, userid); int i = pst.executeUpdate(); - usernameforclass = username; + + Authentication newAuthentication = new UsernamePasswordAuthenticationToken( + username, + password, + SecurityContextHolder.getContext().getAuthentication().getAuthorities()); + + SecurityContextHolder.getContext().setAuthentication(newAuthentication); } catch(Exception e) { System.out.println("Exception:"+e); } - return "redirect:/index"; + return "redirect:index"; } } diff --git a/JtProject/src/main/java/com/jtspringproject/JtSpringProject/controller/ErrorController.java b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/controller/ErrorController.java new file mode 100644 index 00000000..d3496348 --- /dev/null +++ b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/controller/ErrorController.java @@ -0,0 +1,13 @@ +package com.jtspringproject.JtSpringProject.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class ErrorController { + + @GetMapping("/403") + public String accessDenied() { + return "403"; + } +} diff --git a/JtProject/src/main/java/com/jtspringproject/JtSpringProject/controller/UserController.java b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/controller/UserController.java index c5643bbb..05d5834c 100644 --- a/JtProject/src/main/java/com/jtspringproject/JtSpringProject/controller/UserController.java +++ b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/controller/UserController.java @@ -13,11 +13,11 @@ import java.util.ArrayList; import java.util.List; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletRequest; import com.jtspringproject.JtSpringProject.services.cartService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; @@ -27,16 +27,17 @@ import com.jtspringproject.JtSpringProject.services.productService; import com.jtspringproject.JtSpringProject.services.cartService; - - @Controller public class UserController{ - - @Autowired - private userService userService; + + private final userService userService; + private final productService productService; @Autowired - private productService productService; + public UserController(userService userService, productService productService) { + this.userService = userService; + this.productService = productService; + } @GetMapping("/register") public String registerUser() @@ -49,43 +50,32 @@ public String buy() { return "buy"; } - - @GetMapping("/") - public String userlogin(Model model) { - - return "userLogin"; + @GetMapping("/login") + public ModelAndView userlogin(@RequestParam(required = false) String error) { + ModelAndView mv = new ModelAndView("userLogin"); + if ("true".equals(error)) { + mv.addObject("msg", "Please enter correct email and password"); + } + return mv; } - @RequestMapping(value = "userloginvalidate", method = RequestMethod.POST) - public ModelAndView userlogin( @RequestParam("username") String username, @RequestParam("password") String pass,Model model,HttpServletResponse res) { - - System.out.println(pass); - User u = this.userService.checkLogin(username, pass); - System.out.println(u.getUsername()); - - if(username.equals(u.getUsername())) { - - res.addCookie(new Cookie("username", u.getUsername())); - ModelAndView mView = new ModelAndView("index"); - mView.addObject("user", u); - List products = this.productService.getProducts(); - - if (products.isEmpty()) { - mView.addObject("msg", "No products are available"); - } else { - mView.addObject("products", products); - } - return mView; + + @GetMapping("/") + public ModelAndView indexPage() + { + ModelAndView mView = new ModelAndView("index"); + String username = SecurityContextHolder.getContext().getAuthentication().getName(); + mView.addObject("username", username); + List products = this.productService.getProducts(); - }else { - ModelAndView mView = new ModelAndView("userLogin"); - mView.addObject("msg", "Please enter correct email and password"); - return mView; + if (products.isEmpty()) { + mView.addObject("msg", "No products are available"); + } else { + mView.addObject("products", products); } - + return mView; } - @GetMapping("/user/products") public ModelAndView getproduct() { @@ -101,6 +91,7 @@ public ModelAndView getproduct() { return mView; } + @RequestMapping(value = "newuserregister", method = RequestMethod.POST) public ModelAndView newUseRegister(@ModelAttribute User user) { @@ -122,9 +113,27 @@ public ModelAndView newUseRegister(@ModelAttribute User user) return mView; } } + + @GetMapping("/profileDisplay") + public String profileDisplay(Model model, HttpServletRequest request) { + + String username = SecurityContextHolder.getContext().getAuthentication().getName(); + User user = userService.getUserByUsername(username); + if (user != null) { + model.addAttribute("userid", user.getId()); + model.addAttribute("username", user.getUsername()); + model.addAttribute("email", user.getEmail()); + model.addAttribute("password", user.getPassword()); + model.addAttribute("address", user.getAddress()); + } else { + model.addAttribute("msg", "User not found"); + } + + return "updateProfile"; + } - + //for Learning purpose of model @GetMapping("/test") public String Test(Model model) @@ -170,4 +179,4 @@ public ModelAndView Test2() // Listcarts = cartService.getCarts(); // } -} +} \ No newline at end of file diff --git a/JtProject/src/main/java/com/jtspringproject/JtSpringProject/dao/userDao.java b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/dao/userDao.java index f2478a97..f597f1fc 100644 --- a/JtProject/src/main/java/com/jtspringproject/JtSpringProject/dao/userDao.java +++ b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/dao/userDao.java @@ -67,4 +67,17 @@ public boolean userExists(String username) { query.setParameter("username",username); return !query.getResultList().isEmpty(); } -} + + @Transactional + public User getUserByUsername(String username) { + Query query = sessionFactory.getCurrentSession().createQuery("from User where username = :username", User.class); + query.setParameter("username", username); + + try { + return query.getSingleResult(); + } catch (Exception e) { + System.out.println(e.getMessage()); + return null; + } + } +} \ No newline at end of file diff --git a/JtProject/src/main/java/com/jtspringproject/JtSpringProject/models/User.java b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/models/User.java index f65e9f28..106cf85b 100644 --- a/JtProject/src/main/java/com/jtspringproject/JtSpringProject/models/User.java +++ b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/models/User.java @@ -15,7 +15,7 @@ public class User { @Id - @GeneratedValue(strategy=GenerationType.AUTO) + @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; @Column(unique = true) diff --git a/JtProject/src/main/java/com/jtspringproject/JtSpringProject/services/userService.java b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/services/userService.java index 7ae0b9c4..92f48166 100644 --- a/JtProject/src/main/java/com/jtspringproject/JtSpringProject/services/userService.java +++ b/JtProject/src/main/java/com/jtspringproject/JtSpringProject/services/userService.java @@ -4,6 +4,7 @@ import java.util.List; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Service; import com.jtspringproject.JtSpringProject.dao.userDao; @@ -19,7 +20,12 @@ public List getUsers(){ } public User addUser(User user) { - return this.userDao.saveUser(user); + try { + return this.userDao.saveUser(user); + } catch (DataIntegrityViolationException e) { + // handle unique constraint violation, e.g., by throwing a custom exception + throw new RuntimeException("Add user error"); + } } public User checkLogin(String username,String password) { @@ -29,4 +35,8 @@ public User checkLogin(String username,String password) { public boolean checkUserExists(String username) { return this.userDao.userExists(username); } + + public User getUserByUsername(String username) { + return userDao.getUserByUsername(username); + } } diff --git a/JtProject/src/main/resources/application.properties b/JtProject/src/main/resources/application.properties index cdd752aa..fa9181f4 100644 --- a/JtProject/src/main/resources/application.properties +++ b/JtProject/src/main/resources/application.properties @@ -1,4 +1,5 @@ - +# Server configuration +server.port=8080 spring.mvc.view.prefix=/views/ spring.mvc.view.suffix=.jsp @@ -27,7 +28,7 @@ spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true db.driver= com.mysql.cj.jdbc.Driver db.url= jdbc:mysql://localhost:3306/ecommjava?createDatabaseIfNotExist=true db.username= root -db.password= pass +db.password= entitymanager.packagesToScan= com #spring.datasource.url=jdbc:mysql://localhost:3306/ecommjava?createDatabaseIfNotExist=true diff --git a/JtProject/src/main/webapp/views/403.jsp b/JtProject/src/main/webapp/views/403.jsp new file mode 100644 index 00000000..46f6bb84 --- /dev/null +++ b/JtProject/src/main/webapp/views/403.jsp @@ -0,0 +1,58 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +403 - Forbidden + + + +
+

403 - Forbidden

+

Sorry, you do not have permission to access this page.

+
+ + diff --git a/JtProject/src/main/webapp/views/adminHome.jsp b/JtProject/src/main/webapp/views/adminHome.jsp index 229a2e3f..f8c7993d 100644 --- a/JtProject/src/main/webapp/views/adminHome.jsp +++ b/JtProject/src/main/webapp/views/adminHome.jsp @@ -33,9 +33,9 @@