Changeset 8bcd64c
- Timestamp:
- 04/19/23 21:19:08 (19 months ago)
- Branches:
- master
- Children:
- 950fa0d
- Parents:
- 9050790
- Location:
- src/main
- Files:
-
- 5 added
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
src/main/java/edu/gjoko/schedlr/config/AppConfig.java
r9050790 r8bcd64c 5 5 import org.springframework.security.config.core.GrantedAuthorityDefaults; 6 6 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 7 import org.springframework.security.web.authentication.AuthenticationFailureHandler; 7 8 import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 8 9 … … 15 16 16 17 @Bean 17 public AuthenticationSuccessHandler myApplicationAuthenticationSuccessHandler() {18 public AuthenticationSuccessHandler appAuthenticationSuccessHandler() { 18 19 return new AppAuthenticationSuccessHandler(); 20 } 21 22 @Bean 23 public AuthenticationFailureHandler appAuthenticationFailureHandler() { 24 return new AppAuthenticationFailureHandler(); 19 25 } 20 26 -
src/main/java/edu/gjoko/schedlr/config/AppFilter.java
r9050790 r8bcd64c 1 1 package edu.gjoko.schedlr.config; 2 2 3 import edu.gjoko.schedlr.services.PostgresUserDetailsService; 4 import lombok.RequiredArgsConstructor; 3 5 import org.springframework.security.core.GrantedAuthority; 4 6 import org.springframework.security.core.context.SecurityContextImpl; 5 7 import org.springframework.security.core.userdetails.UserDetails; 6 8 import org.springframework.util.StringUtils; 9 import org.springframework.web.bind.annotation.RequestBody; 7 10 import org.springframework.web.filter.GenericFilterBean; 8 11 … … 12 15 import javax.servlet.ServletResponse; 13 16 import javax.servlet.http.HttpServletRequest; 17 import javax.servlet.http.HttpServletResponse; 14 18 import javax.servlet.http.HttpSession; 15 19 import java.io.IOException; … … 18 22 import java.util.Map; 19 23 24 @RequiredArgsConstructor 20 25 public class AppFilter extends GenericFilterBean { 26 27 private final PostgresUserDetailsService userDetailsService; 21 28 @Override 22 29 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 23 30 HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; 24 31 HttpSession session = httpServletRequest.getSession(false); 32 HttpServletResponse response = (HttpServletResponse) servletResponse; 25 33 26 34 if(httpServletRequest.getRequestURI().endsWith(".js") 27 || httpServletRequest.getRequestURI().endsWith(".css") 28 || httpServletRequest.getRequestURI().startsWith("/api")) { 35 || httpServletRequest.getRequestURI().endsWith(".css")) { 29 36 filterChain.doFilter(servletRequest, servletResponse); 30 37 return; 31 38 } 39 40 if(httpServletRequest.getRequestURI().startsWith("/api")) { 41 session = ((HttpServletRequest) servletRequest).getSession(true); 42 SecurityContextImpl sci = (SecurityContextImpl) session.getAttribute("SPRING_SECURITY_CONTEXT"); 43 44 if(sci != null && session.getAttribute("stakeholderId") == null) { 45 UserDetails userDetails = (UserDetails) sci.getAuthentication().getPrincipal(); 46 Long stakeholderId = userDetailsService.loadStakeholderId(userDetails.getUsername()); 47 session.setAttribute("stakeholderId", stakeholderId); 48 } 49 filterChain.doFilter(servletRequest, servletResponse); 50 return; 51 } 52 32 53 if(session != null) { 33 Map<String, String> roleTargetUrlMap = new HashMap<>();34 roleTargetUrlMap.put("ADMIN", "/admin");35 roleTargetUrlMap.put("CUSTOMER", "/homepage");36 roleTargetUrlMap.put("BUSINESS_OWNER", "/business_homepage");37 54 SecurityContextImpl sci = (SecurityContextImpl) session.getAttribute("SPRING_SECURITY_CONTEXT"); 38 55 if(sci != null) { 39 56 UserDetails userDetails = (UserDetails) sci.getAuthentication().getPrincipal(); 57 Long stakeholderId = userDetailsService.loadStakeholderId(userDetails.getUsername()); 58 session.setAttribute("stakeholderId", stakeholderId); 59 40 60 final Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities(); 41 61 for (final GrantedAuthority grantedAuthority : authorities) { … … 47 67 break; 48 68 case "CUSTOMER": 69 page = "/homepage"; 70 break; 49 71 case "BUSINESS_OWNER": 50 page = "/ homepage";72 page = "/business_admin"; 51 73 break; 52 74 default: -
src/main/java/edu/gjoko/schedlr/config/AppSecurityConfig.java
r9050790 r8bcd64c 2 2 3 3 import edu.gjoko.schedlr.services.PostgresUserDetailsService; 4 import lombok.AllArgsConstructor; 4 5 import org.springframework.context.annotation.Bean; 5 6 import org.springframework.context.annotation.Configuration; … … 11 12 import org.springframework.security.config.core.GrantedAuthorityDefaults; 12 13 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 14 import org.springframework.security.web.access.AccessDeniedHandler; 15 import org.springframework.security.web.authentication.AuthenticationFailureHandler; 13 16 import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 14 17 import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; … … 16 19 @Configuration 17 20 @EnableWebSecurity 21 @AllArgsConstructor 18 22 public class AppSecurityConfig extends WebSecurityConfigurerAdapter { 19 23 … … 24 28 private final AuthenticationSuccessHandler authenticationSuccessHandler; 25 29 26 public AppSecurityConfig(PostgresUserDetailsService userDetailsService, BCryptPasswordEncoder passwordEncoder, 27 AuthenticationSuccessHandler authenticationSuccessHandler) { 28 this.userDetailsService = userDetailsService; 29 this.passwordEncoder = passwordEncoder; 30 this.authenticationSuccessHandler = authenticationSuccessHandler; 31 } 30 private final AuthenticationFailureHandler authenticationFailureHandler; 32 31 33 32 @Bean … … 48 47 .authenticationEntryPoint(new AppAuthenticationEntryPoint()) 49 48 .and() 50 .addFilter Before(new AppFilter(), BasicAuthenticationFilter.class)49 .addFilterAfter(new AppFilter(userDetailsService), BasicAuthenticationFilter.class) 51 50 .formLogin() 52 51 .loginPage("/login") 53 52 .loginProcessingUrl("/login") 54 53 .successHandler(authenticationSuccessHandler) 54 .failureHandler(authenticationFailureHandler) 55 55 .defaultSuccessUrl("/homepage") 56 56 .and() -
src/main/java/edu/gjoko/schedlr/config/MvcConfig.java
r9050790 r8bcd64c 2 2 3 3 import org.springframework.context.annotation.Configuration; 4 import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;5 4 import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 6 5 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; … … 16 15 registry.addViewController("/homepage").setViewName("homepage"); 17 16 registry.addViewController("/admin").setViewName("admin"); 18 } 19 20 @Override 21 public void addResourceHandlers(ResourceHandlerRegistry registry) { 22 registry.addResourceHandler("/resources/**") 23 .addResourceLocations("/resources/"); 17 registry.addViewController("/business_admin").setViewName("business_admin"); 24 18 } 25 19 } -
src/main/java/edu/gjoko/schedlr/controllers/AdminController.java
r9050790 r8bcd64c 1 1 package edu.gjoko.schedlr.controllers; 2 2 3 import org.springframework.security.core.Authentication; 4 import org.springframework.security.core.context.SecurityContextHolder; 3 5 import org.springframework.stereotype.Controller; 4 6 import org.springframework.ui.Model; 5 7 import org.springframework.web.bind.annotation.GetMapping; 8 9 import javax.servlet.http.HttpServletRequest; 10 import java.security.Principal; 6 11 7 12 @Controller … … 9 14 10 15 @GetMapping(path = "/admin") 11 public String getAdminPageTemplate(Model model ) {16 public String getAdminPageTemplate(Model model, HttpServletRequest request) { 12 17 return "admin"; 13 18 } 19 20 @GetMapping(path = "/business_admin") 21 public String getBusinessAdminPageTemplate(Model model, HttpServletRequest request) { 22 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 23 String currentPrincipalName = authentication.getName(); 24 25 return "business_admin"; 26 } 27 28 14 29 } -
src/main/java/edu/gjoko/schedlr/controllers/HomePageController.java
r9050790 r8bcd64c 6 6 import org.springframework.web.bind.annotation.PostMapping; 7 7 8 import java.security.Principal;9 10 8 @Controller 11 9 public class HomePageController { 12 10 13 11 @GetMapping(path = "/homepage") 14 public String getHomePageTemplate(Model model, Principal principal) { 15 System.out.println(principal); 12 public String getHomePageTemplate(Model model) { 16 13 return "homepage"; 17 14 } -
src/main/java/edu/gjoko/schedlr/controllers/LoginController.java
r9050790 r8bcd64c 7 7 import org.springframework.web.bind.annotation.ModelAttribute; 8 8 import org.springframework.web.bind.annotation.PostMapping; 9 import org.springframework.web.bind.annotation.RequestParam; 10 11 import java.security.Principal; 9 12 10 13 @Controller … … 12 15 13 16 @GetMapping(path = "/login") 14 public String getMapping(@ModelAttribute Stakeholder customer, Model model) { 17 public String getMapping(@RequestParam(value = "error", required = false) String error, 18 @ModelAttribute Stakeholder customer, Model model) { 15 19 return "login"; 16 20 } -
src/main/java/edu/gjoko/schedlr/controllers/RegisterController.java
r9050790 r8bcd64c 28 28 @PostMapping(path = "/register_customer") 29 29 public String registerCustomer(@ModelAttribute Stakeholder customer, Model model) { 30 Stakeholder user =stakeholderService.saveStakeholder(customer);30 stakeholderService.saveStakeholder(customer); 31 31 return "redirect:login"; 32 32 } -
src/main/java/edu/gjoko/schedlr/controllers/rest/BusinessController.java
r9050790 r8bcd64c 4 4 import edu.gjoko.schedlr.services.BusinessService; 5 5 import lombok.AllArgsConstructor; 6 import org.springframework.security.core.Authentication; 7 import org.springframework.security.core.context.SecurityContextHolder; 6 8 import org.springframework.web.bind.annotation.*; 7 9 10 import javax.servlet.http.HttpServletRequest; 8 11 import java.util.List; 9 12 … … 29 32 businessService.updateBusinesses(businessList); 30 33 } 34 35 @GetMapping(path = "/me") 36 public Business getPersonalInfo(HttpServletRequest request) { 37 Long businessOwnerId = (long) request.getSession(true).getAttribute("stakeholderId"); 38 return businessService.findByOwner(businessOwnerId); 39 } 31 40 } -
src/main/java/edu/gjoko/schedlr/entity/Business.java
r9050790 r8bcd64c 1 1 package edu.gjoko.schedlr.entity; 2 2 3 import com.fasterxml.jackson.annotation.JsonIgnore; 3 4 import com.fasterxml.jackson.annotation.JsonManagedReference; 4 5 import com.fasterxml.jackson.annotation.JsonProperty; … … 51 52 @Column(name = "created") 52 53 @CreatedDate 54 @JsonIgnore 53 55 private LocalDateTime created; 54 56 55 57 @Column(name = "modified") 56 58 @LastModifiedDate 59 @JsonIgnore 57 60 private LocalDateTime modified; 58 61 -
src/main/java/edu/gjoko/schedlr/entity/Service.java
r9050790 r8bcd64c 2 2 3 3 import com.fasterxml.jackson.annotation.JsonBackReference; 4 import com.fasterxml.jackson.annotation.JsonIgnore; 4 5 import lombok.AllArgsConstructor; 5 6 import lombok.Getter; … … 29 30 private Integer duration; 30 31 32 @Column(name = "price") 33 private Integer price; 34 31 35 @OneToOne(cascade = CascadeType.MERGE) 32 36 @JoinColumn(name = "service_type_id", referencedColumnName = "id") … … 40 44 @Column(name = "created") 41 45 @CreatedDate 46 @JsonIgnore 42 47 private LocalDateTime created; 43 48 44 49 @Column(name = "modified") 45 50 @LastModifiedDate 51 @JsonIgnore 46 52 private LocalDateTime modified; 47 53 } -
src/main/java/edu/gjoko/schedlr/entity/Stakeholder.java
r9050790 r8bcd64c 1 1 package edu.gjoko.schedlr.entity; 2 2 3 import com.fasterxml.jackson.annotation.JsonIgnore; 3 4 import lombok.AllArgsConstructor; 4 5 import lombok.Getter; … … 42 43 43 44 @Column(name = "password") 45 @JsonIgnore 44 46 private String password; 45 47 46 48 @Column(name = "created") 47 49 @CreatedDate 50 @JsonIgnore 48 51 private LocalDateTime created; 49 52 50 53 @Column(name = "modified") 51 54 @LastModifiedDate 55 @JsonIgnore 52 56 private LocalDateTime modified; 53 57 } -
src/main/java/edu/gjoko/schedlr/repositories/BusinessRepository.java
r9050790 r8bcd64c 3 3 import edu.gjoko.schedlr.entity.Business; 4 4 import edu.gjoko.schedlr.entity.BusinessStatus; 5 import edu.gjoko.schedlr.entity.Stakeholder; 5 6 import org.springframework.data.jpa.repository.JpaRepository; 6 7 import org.springframework.stereotype.Repository; … … 12 13 13 14 List<Business> findBusinessesByBusinessStatus(BusinessStatus status); 15 16 Business findBusinessByOwner(Stakeholder owner); 14 17 } -
src/main/java/edu/gjoko/schedlr/services/BusinessService.java
r9050790 r8bcd64c 3 3 import edu.gjoko.schedlr.entity.Business; 4 4 import edu.gjoko.schedlr.entity.ServiceType; 5 import edu.gjoko.schedlr.entity.Stakeholder; 5 6 import edu.gjoko.schedlr.entity.StakeholderType; 6 7 import edu.gjoko.schedlr.repositories.BusinessRepository; 7 8 import edu.gjoko.schedlr.repositories.ServiceTypeRepository; 8 9 import lombok.AllArgsConstructor; 10 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 9 11 import org.springframework.stereotype.Service; 10 12 11 13 import java.util.List; 12 14 13 import static edu.gjoko.schedlr.entity.BusinessStatus.ACTIVE;14 15 import static edu.gjoko.schedlr.entity.BusinessStatus.NEW; 15 16 … … 20 21 private final BusinessRepository businessRepository; 21 22 private final ServiceTypeRepository serviceTypeRepository; 23 private BCryptPasswordEncoder bCryptPasswordEncoder; 22 24 23 25 public void saveBusiness(Business business) { 24 26 saveNewServiceTypes(business); 25 27 business.getOwner().setStakeholderType(StakeholderType.BUSINESS_OWNER); 28 business.getOwner().setPassword(bCryptPasswordEncoder.encode(business.getOwner().getPassword())); 26 29 business.setBusinessStatus(NEW); 27 30 businessRepository.save(business); … … 52 55 } 53 56 57 public Business findByOwner(Long ownerId) { 58 var owner = new Stakeholder(); 59 owner.setId(ownerId); 60 return businessRepository.findBusinessByOwner(owner); 61 } 54 62 } -
src/main/java/edu/gjoko/schedlr/services/PostgresUserDetailsService.java
r9050790 r8bcd64c 1 1 package edu.gjoko.schedlr.services; 2 2 3 import edu.gjoko.schedlr.entity.Business; 4 import edu.gjoko.schedlr.entity.BusinessStatus; 3 5 import edu.gjoko.schedlr.entity.Stakeholder; 6 import edu.gjoko.schedlr.entity.StakeholderType; 7 import edu.gjoko.schedlr.repositories.BusinessRepository; 4 8 import edu.gjoko.schedlr.repositories.StakeholderRepository; 9 import lombok.RequiredArgsConstructor; 10 import org.springframework.security.access.AccessDeniedException; 5 11 import org.springframework.security.core.GrantedAuthority; 6 12 import org.springframework.security.core.authority.SimpleGrantedAuthority; … … 16 22 17 23 @Service 24 @RequiredArgsConstructor 18 25 public class PostgresUserDetailsService implements UserDetailsService { 19 26 … … 21 28 private final BCryptPasswordEncoder bCryptPasswordEncoder; 22 29 23 public PostgresUserDetailsService(StakeholderRepository stakeholderRepository, 24 BCryptPasswordEncoder bCryptPasswordEncoder) { 25 this.stakeholderRepository = stakeholderRepository; 26 this.bCryptPasswordEncoder = bCryptPasswordEncoder; 27 } 30 private final BusinessRepository businessRepository; 28 31 29 32 @Override … … 33 36 throw new UsernameNotFoundException("Non existing user"); 34 37 } 38 39 if(user.getStakeholderType() == StakeholderType.BUSINESS_OWNER) { 40 Business business = businessRepository.findBusinessByOwner(user); 41 if (business.getBusinessStatus() != BusinessStatus.ACTIVE) { 42 throw new SecurityException("User not approved by admin"); 43 } 44 } 35 45 Set<GrantedAuthority> grantedAuthorities = new HashSet<>(); 36 46 grantedAuthorities.add(new SimpleGrantedAuthority(user.getStakeholderType().name())); 47 37 48 return new User(user.getUsername(), user.getPassword(), grantedAuthorities); 38 49 } 50 51 public Long loadStakeholderId(String username) { 52 return stakeholderRepository.findStakeholderByUsername(username).getId(); 53 } 39 54 } -
src/main/resources/static/js/register_business.js
r9050790 r8bcd64c 22 22 '<div class=\"form-outline mb-4\">' + 23 23 ' <div class="row">' + 24 ' <div class="col-md- 8">\n' +24 ' <div class="col-md-6">\n' + 25 25 ' <input class="form-check-input" type="checkbox" value=\"' + obj.id + '\" id=\"' + obj.id + '\">\n' + 26 26 ' <label class="form-check-label" for=\"' + obj.id + '\">\n' + … … 29 29 ' </div>' + 30 30 ' <div class=\"form-outline col-md-2 d-grid\">' + 31 ' <input type=\"text\" id=\"' + obj.id + obj.name.replace(/\s/g, "") + '\" class=\"form-control\" />' + 31 ' <input type=\"text\" id=\"' + obj.id + obj.name.replace(/\s/g, "") + "duration" + '\" class=\"form-control\" placeholder="time" />' + 32 ' </div>' + 33 ' <div class=\"form-outline col-md-2 d-grid\">' + 34 ' <input type=\"text\" id=\"' + obj.id + obj.name.replace(/\s/g, "") + "price" + '\" class=\"form-control\" placeholder="price" />' + 32 35 ' </div>' + 33 36 ' </div>' + … … 53 56 ' </div>' + 54 57 ' <div class="form-outline col-md-2 d-grid">' + 55 ' <input type="text" id="' + -1 + input_service.replace(/\s/g, "") + '" class="form-control" />' + 58 ' <input type="text" id="' + -1 + input_service.replace(/\s/g, "") + "duration" + '" class="form-control" placeholder="time" />' + 59 ' </div>' + 60 ' <div class="form-outline col-md-2 d-grid">' + 61 ' <input type="text" id="' + -1 + input_service.replace(/\s/g, "") + "price"+ '" class="form-control" placeholder="price" />' + 56 62 ' </div>' + 57 63 ' </div>' + … … 83 89 var text = $(label).text(); 84 90 var time = $($($(label).parent()).siblings()[0]).children()[0].value; 91 var price = $($($(label).parent()).siblings()[1]).children()[0].value; 85 92 86 93 var serviceType = {} … … 91 98 service['serviceType'] = serviceType; 92 99 service['duration'] = time; 100 service['price'] = price; 93 101 servicesObj.push(service); 94 102 }); -
src/main/resources/templates/admin.html
r9050790 r8bcd64c 2 2 <html lang="en"> 3 3 <head> 4 <title> Schedlr</title>4 <title>Admin</title> 5 5 6 6 <meta charset="utf-8"/> -
src/main/resources/templates/homepage.html
r9050790 r8bcd64c 2 2 <html> 3 3 <head> 4 <title> Schedlr</title>4 <title>Homepage</title> 5 5 6 6 <meta charset="utf-8"/> -
src/main/resources/templates/login.html
r9050790 r8bcd64c 3 3 <head> 4 4 <meta charset="UTF-8"> 5 <title> Schedlr</title>5 <title>Login</title> 6 6 7 7 <!-- Font Awesome --> … … 54 54 55 55 <!-- Submit button --> 56 <button type="submit" class="btn btn-primary btn-block mb-4">56 <button id="login" type="submit" class="btn btn-primary btn-block mb-4"> 57 57 Login 58 58 </button> 59 <div th:if="${param.error}"> 60 <div th:if="${param.error.contains('notApproved')}" class="alert alert-danger"> 61 Account not approved yet. 62 </div> 63 64 <div th:if="${param.error.contains('badCredentials')}" class="alert alert-danger"> 65 Invalid username or password. 66 </div> 67 </div> 59 68 </form> 60 69 -
src/main/resources/templates/register_business.html
r9050790 r8bcd64c 3 3 <head> 4 4 <meta charset="UTF-8"> 5 <title>Schedlr</title> 6 5 <title>Register business</title> 7 6 <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" 8 7 integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous"> 9 10 8 <link rel="stylesheet" href="css/login.css"> 11 12 9 </head> 13 10 <body> … … 30 27 <form> 31 28 <div class="text-center"> 32 33 29 <p>Personal Info</p> 30 </div> 34 31 35 32 <!-- 2 column grid layout with text inputs for the first and last names --> -
src/main/resources/templates/register_customer.html
r9050790 r8bcd64c 3 3 <head> 4 4 <meta charset="UTF-8"> 5 <title> Schedlr</title>5 <title>Register customer</title> 6 6 7 7 <meta charset="utf-8"/>
Note:
See TracChangeset
for help on using the changeset viewer.