diff --git a/shoppingcart/pom.xml b/shoppingcart/pom.xml index 41bcda7a..c749b4de 100644 --- a/shoppingcart/pom.xml +++ b/shoppingcart/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.2.8.RELEASE + 2.2.9.RELEASE com.lambdaschool @@ -15,7 +15,7 @@ Demo project for Spring Boot - 14 + 11 @@ -63,6 +63,23 @@ javafaker 1.0.1 + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security + spring-security-test + test + + + org.springframework.security.oauth + spring-security-oauth2 + 2.3.6.RELEASE + + diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/config/AuthorizationServerConfig.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/config/AuthorizationServerConfig.java new file mode 100644 index 00000000..1af83d69 --- /dev/null +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/config/AuthorizationServerConfig.java @@ -0,0 +1,50 @@ +package com.lambdaschool.shoppingcart.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.provider.token.TokenStore; + +@Configuration +@EnableAuthorizationServer +public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { + static final String CLIENT_ID = System.getenv("OAUTHCLIENTID"); + static final String CLIENT_SECRET = System.getenv("OAUTHCLIENTSECRET"); + static final String GRANT_TYPE_PASSWORD = "password"; + static final String AUTHORIZATION_CODE = "authorization_code"; + static final String SCOPE_WRITE = "write"; + static final String SCOPE_READ = "read"; + static final String TRUST = "trust"; + static final int ACCESS_TOKEN_VALIDITY_SECONDS = -1; + + @Autowired + private TokenStore tokenStore; + + @Autowired + private AuthenticationManager authenticationManager; + + @Autowired + private PasswordEncoder encoder; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + clients.inMemory() + .withClient(CLIENT_ID) + .secret(encoder.encode(CLIENT_SECRET)) + .authorizedGrantTypes(GRANT_TYPE_PASSWORD, AUTHORIZATION_CODE) + .scopes(SCOPE_WRITE, SCOPE_READ, TRUST) + .accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS); + } + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenStore(tokenStore) + .authenticationManager(authenticationManager); + endpoints.pathMapping("/oauth/token", "/login"); + } +} diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/config/ResourceServerConfig.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/config/ResourceServerConfig.java new file mode 100644 index 00000000..ef104a1a --- /dev/null +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/config/ResourceServerConfig.java @@ -0,0 +1,36 @@ +package com.lambdaschool.shoppingcart.config; + + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; + +@Configuration +@EnableResourceServer +public class ResourceServerConfig extends ResourceServerConfigurerAdapter { + + private static final String RESOURCE_ID = "resource_id"; + + @Override + public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + resources.resourceId(RESOURCE_ID).stateless(false); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + http.csrf().disable(); + http.headers().frameOptions().disable(); + http.logout().disable(); + + http.authorizeRequests() + .antMatchers("/", "/h2-console/**").permitAll() + .antMatchers("/users/**").hasAnyRole("ADMIN", "USER") + .antMatchers("/products/**").hasAnyRole("ADMIN", "USER") + .and() + .exceptionHandling() + .accessDeniedHandler(new OAuth2AccessDeniedHandler()); + } +} diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/config/SecurityConfig.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/config/SecurityConfig.java new file mode 100644 index 00000000..cd5c8550 --- /dev/null +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/config/SecurityConfig.java @@ -0,0 +1,50 @@ +package com.lambdaschool.shoppingcart.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; + +import javax.annotation.Resource; + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + @Bean + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Resource(name = "securityUserService") + private UserDetailsService userDetailsService; + + @Autowired + public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception + { + auth.userDetailsService(userDetailsService).passwordEncoder(encoder()); + } + + @Bean + public TokenStore tokenStore(){ + return new InMemoryTokenStore(); + } + + @Bean + public PasswordEncoder encoder(){ + return new BCryptPasswordEncoder(); + } + +} diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/controllers/CartController.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/controllers/CartController.java index 62610dd4..a6d669ac 100644 --- a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/controllers/CartController.java +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/controllers/CartController.java @@ -4,9 +4,12 @@ import com.lambdaschool.shoppingcart.models.Product; import com.lambdaschool.shoppingcart.models.User; import com.lambdaschool.shoppingcart.services.CartService; +import com.lambdaschool.shoppingcart.services.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -24,13 +27,18 @@ public class CartController @Autowired private CartService cartService; + @Autowired + private UserService userService; + @GetMapping(value = "/user", produces = {"application/json"}) - public ResponseEntity listAllCarts(@PathVariable long userid) + public ResponseEntity listAllCarts(Authentication authentication) { - List myCarts = cartService.findAllByUserId(userid); + User currentUser = userService.findByName(authentication.getName()); + List myCarts = cartService.findAllByUserId(currentUser.getUserid()); return new ResponseEntity<>(myCarts, HttpStatus.OK); } + @PreAuthorize("hasAnyRole('ADMIN')") @GetMapping(value = "/cart/{cartId}", produces = {"application/json"}) public ResponseEntity getCartById( @@ -42,12 +50,12 @@ public ResponseEntity getCartById( HttpStatus.OK); } - @PostMapping(value = "/create/user/{userid}/product/{productid}") - public ResponseEntity addNewCart(@PathVariable long userid, + @PostMapping(value = "/create/product/{productid}") + public ResponseEntity addNewCart(Authentication authentication, @PathVariable long productid) { User dataUser = new User(); - dataUser.setUserid(userid); + dataUser.setUserid(userService.findByName(authentication.getName()).getUserid()); Product dataProduct = new Product(); dataProduct.setProductid(productid); diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/controllers/UserController.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/controllers/UserController.java index 85fdd7c5..ebfdb34f 100644 --- a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/controllers/UserController.java +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/controllers/UserController.java @@ -6,6 +6,8 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -26,6 +28,7 @@ public class UserController @Autowired private UserService userService; + @PreAuthorize("hasAnyRole('ADMIN')") @GetMapping(value = "/users", produces = {"application/json"}) public ResponseEntity listAllUsers() { @@ -33,6 +36,7 @@ public ResponseEntity listAllUsers() return new ResponseEntity<>(myUsers, HttpStatus.OK); } + @PreAuthorize("hasAnyRole('ADMIN')") @GetMapping(value = "/user/{userId}", produces = {"application/json"}) public ResponseEntity getUserById( @@ -44,6 +48,7 @@ public ResponseEntity getUserById( HttpStatus.OK); } + @PreAuthorize("hasAnyRole('ADMIN')") @PostMapping(value = "/user", consumes = {"application/json"}) public ResponseEntity addUser(@Valid @RequestBody User newuser) { @@ -63,6 +68,7 @@ public ResponseEntity addUser(@Valid @RequestBody User newuser) HttpStatus.CREATED); } + @PreAuthorize("hasAnyRole('ADMIN')") @DeleteMapping(value = "/user/{userId}") public ResponseEntity deleteUserById( @PathVariable @@ -71,4 +77,12 @@ public ResponseEntity deleteUserById( userService.delete(userId); return new ResponseEntity<>(HttpStatus.OK); } + + // http://localhost:2019/users/myinfo + @GetMapping(value = "/myinfo", produces = "application/json") + public ResponseEntity getMyInfo(Authentication authentication) + { + User myInfo = userService.findByName(authentication.getName()); + return new ResponseEntity<>(myInfo, HttpStatus.OK); + } } diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/models/Role.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/models/Role.java new file mode 100644 index 00000000..919381fc --- /dev/null +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/models/Role.java @@ -0,0 +1,54 @@ +package com.lambdaschool.shoppingcart.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.persistence.*; +import java.util.HashSet; +import java.util.Set; + +@Entity +@Table(name = "roles") +public class Role extends Auditable{ + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long roleid; + + @Column(nullable = false, unique = true) + private String name; + + @OneToMany(mappedBy = "role", cascade = CascadeType.ALL, orphanRemoval = true) + @JsonIgnoreProperties(value = "role", allowSetters = true) + private Set users = new HashSet<>(); + + public Role() { + } + + public Role(String name) { + this.name = name.toUpperCase(); + } + + public long getRoleid() { + return roleid; + } + + public void setRoleid(long roleid) { + this.roleid = roleid; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name.toUpperCase(); + } + + public Set getUsers() { + return users; + } + + public void setUsers(Set users) { + this.users = users; + } +} diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/models/User.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/models/User.java index f9682f15..c439b609 100644 --- a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/models/User.java +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/models/User.java @@ -1,6 +1,9 @@ package com.lambdaschool.shoppingcart.models; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import javax.persistence.CascadeType; import javax.persistence.Column; @@ -11,7 +14,9 @@ import javax.persistence.OneToMany; import javax.persistence.Table; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; @Entity @Table(name = "users") @@ -26,6 +31,10 @@ public class User unique = true) private String username; + @Column(nullable = false) + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) + private String password; + private String comments; @OneToMany(mappedBy = "user", @@ -34,11 +43,21 @@ public class User allowSetters = true) private List carts = new ArrayList<>(); + @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) + @JsonIgnoreProperties(value = "user", allowSetters = true) + private Set roles = new HashSet<>(); + public User() { } + public User(String username, String password, String comments) { + setUsername(username); + setPassword(password); + this.comments = comments; + } + public long getUserid() { return userid; @@ -78,4 +97,36 @@ public void setCarts(List carts) { this.carts = carts; } + + public Set getRoles() { + return roles; + } + + public void setRoles(Set roles) { + this.roles = roles; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + this.password = passwordEncoder.encode(password); + } + + public void setNoEncodePassword(String password){ + this.password = password; + } + + public List getAuthority(){ + List rtnList = new ArrayList<>(); + for(UserRoles r : this.roles) { + String myRole = "ROLE_" + r.getRole().getName().toUpperCase(); + rtnList.add(new SimpleGrantedAuthority(myRole)); + } + return rtnList; + } + + } diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/models/UserRoles.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/models/UserRoles.java new file mode 100644 index 00000000..c511dfd8 --- /dev/null +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/models/UserRoles.java @@ -0,0 +1,63 @@ +package com.lambdaschool.shoppingcart.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.Objects; + +@Entity +@Table(name = "userroles") +@IdClass(UserRolesId.class) +public class UserRoles extends Auditable implements Serializable { + + @Id + @ManyToOne + @JoinColumn(name = "userid") + @JsonIgnoreProperties(value = "roles", allowSetters = true) + private User user; + + @Id + @ManyToOne + @JoinColumn(name = "roleid") + @JsonIgnoreProperties(value = "users", allowSetters = true) + private Role role; + + public UserRoles() { + } + + public UserRoles(User user, Role role) { + this.user = user; + this.role = role; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Role getRole() { + return role; + } + + public void setRole(Role role) { + this.role = role; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof UserRoles)) return false; + UserRoles that = (UserRoles) o; + return ((user == null) ? 0 : user.getUserid()) == ((that.user == null) ? 0 : that.user.getUserid()) && + ((role == null) ? 0 : role.getRoleid()) == ((that.role == null) ? 0 : that.role.getRoleid()); + } + + @Override + public int hashCode() { + return 37; + } +} diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/models/UserRolesId.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/models/UserRolesId.java new file mode 100644 index 00000000..f22e408e --- /dev/null +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/models/UserRolesId.java @@ -0,0 +1,46 @@ +package com.lambdaschool.shoppingcart.models; + +import javax.persistence.Embeddable; +import java.io.Serializable; +import java.util.Objects; + +@Embeddable +public class UserRolesId implements Serializable { + + private long user; + + private long role; + + public UserRolesId() { + } + + public long getUser() { + return user; + } + + public void setUser(long user) { + this.user = user; + } + + public long getRole() { + return role; + } + + public void setRole(long role) { + this.role = role; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + UserRolesId that = (UserRolesId) o; + return user == that.user && + role == that.role; + } + + @Override + public int hashCode() { + return 37; + } +} diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/repositories/RoleRepository.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/repositories/RoleRepository.java new file mode 100644 index 00000000..ced8b105 --- /dev/null +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/repositories/RoleRepository.java @@ -0,0 +1,7 @@ +package com.lambdaschool.shoppingcart.repositories; + +import com.lambdaschool.shoppingcart.models.Role; +import org.springframework.data.repository.CrudRepository; + +public interface RoleRepository extends CrudRepository { +} diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/repositories/UserRepository.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/repositories/UserRepository.java index 81c73387..30866346 100644 --- a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/repositories/UserRepository.java +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/repositories/UserRepository.java @@ -6,4 +6,5 @@ public interface UserRepository extends CrudRepository { + User findByUsername(String username); } diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/CartServiceImpl.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/CartServiceImpl.java index 69128e89..287c461b 100644 --- a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/CartServiceImpl.java +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/CartServiceImpl.java @@ -37,6 +37,9 @@ public class CartServiceImpl @Autowired private ProductRepository productrepos; + @Autowired + private HelperFunctionService helperFunctionService; + /** * Connects this service to the auditing service in order to get current user name */ @@ -86,23 +89,26 @@ public Cart save(User user, public Cart save(Cart cart, Product product) { - Cart updateCart = cartrepos.findById(cart.getCartid()) - .orElseThrow(() -> new ResourceNotFoundException("Cart Id " + cart.getCartid() + " not found")); - Product updateProduct = productrepos.findById(product.getProductid()) - .orElseThrow(() -> new ResourceNotFoundException("Product id " + product.getProductid() + " not found")); - - if (cartrepos.checkCartItems(updateCart.getCartid(), updateProduct.getProductid()) - .getCount() > 0) - { - cartrepos.updateCartItemsQuantity(userAuditing.getCurrentAuditor() - .get(), updateCart.getCartid(), updateProduct.getProductid(), 1); - } else - { - cartrepos.addCartItems(userAuditing.getCurrentAuditor() - .get(), updateCart.getCartid(), updateProduct.getProductid()); + User currentUser = cart.getUser(); + if(helperFunctionService.isAuthorizedToMakeChange(currentUser.getUsername())) { + Cart updateCart = cartrepos.findById(cart.getCartid()) + .orElseThrow(() -> new ResourceNotFoundException("Cart Id " + cart.getCartid() + " not found")); + Product updateProduct = productrepos.findById(product.getProductid()) + .orElseThrow(() -> new ResourceNotFoundException("Product id " + product.getProductid() + " not found")); + + if (cartrepos.checkCartItems(updateCart.getCartid(), updateProduct.getProductid()) + .getCount() > 0) { + cartrepos.updateCartItemsQuantity(userAuditing.getCurrentAuditor() + .get(), updateCart.getCartid(), updateProduct.getProductid(), 1); + } else { + cartrepos.addCartItems(userAuditing.getCurrentAuditor() + .get(), updateCart.getCartid(), updateProduct.getProductid()); + } + + return cartrepos.save(updateCart); + } else { + throw new ResourceNotFoundException("This user is not authorized to make change"); } - - return cartrepos.save(updateCart); } @Transactional @@ -110,21 +116,24 @@ public Cart save(Cart cart, public void delete(Cart cart, Product product) { - Cart updateCart = cartrepos.findById(cart.getCartid()) - .orElseThrow(() -> new ResourceNotFoundException("Cart Id " + cart.getCartid() + " not found")); - Product updateProduct = productrepos.findById(product.getProductid()) - .orElseThrow(() -> new ResourceNotFoundException("Product id " + product.getProductid() + " not found")); - - if (cartrepos.checkCartItems(updateCart.getCartid(), updateProduct.getProductid()) - .getCount() > 0) - { - cartrepos.updateCartItemsQuantity(userAuditing.getCurrentAuditor() - .get(), updateCart.getCartid(), updateProduct.getProductid(), -1); - cartrepos.removeCartItemsQuantityZero(); - cartrepos.removeCartWithNoProducts(); - } else - { - throw new ResourceNotFoundException("Cart id " + updateCart.getCartid() + " Product id " + updateProduct.getProductid() + " combo not found"); + User currentUser = cart.getUser(); + if(helperFunctionService.isAuthorizedToMakeChange(currentUser.getUsername())) { + Cart updateCart = cartrepos.findById(cart.getCartid()) + .orElseThrow(() -> new ResourceNotFoundException("Cart Id " + cart.getCartid() + " not found")); + Product updateProduct = productrepos.findById(product.getProductid()) + .orElseThrow(() -> new ResourceNotFoundException("Product id " + product.getProductid() + " not found")); + + if (cartrepos.checkCartItems(updateCart.getCartid(), updateProduct.getProductid()) + .getCount() > 0) { + cartrepos.updateCartItemsQuantity(userAuditing.getCurrentAuditor() + .get(), updateCart.getCartid(), updateProduct.getProductid(), -1); + cartrepos.removeCartItemsQuantityZero(); + cartrepos.removeCartWithNoProducts(); + } else { + throw new ResourceNotFoundException("Cart id " + updateCart.getCartid() + " Product id " + updateProduct.getProductid() + " combo not found"); + } + } else { + throw new ResourceNotFoundException("This user is not authorized to make change"); } } } diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/HelperFunctionService.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/HelperFunctionService.java new file mode 100644 index 00000000..1b8a14a6 --- /dev/null +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/HelperFunctionService.java @@ -0,0 +1,6 @@ +package com.lambdaschool.shoppingcart.services; + +public interface HelperFunctionService { + + boolean isAuthorizedToMakeChange(String username); +} diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/HelperFunctionsImpl.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/HelperFunctionsImpl.java new file mode 100644 index 00000000..680c21de --- /dev/null +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/HelperFunctionsImpl.java @@ -0,0 +1,23 @@ +package com.lambdaschool.shoppingcart.services; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; + +import javax.persistence.EntityNotFoundException; + +@Service(value = "helperFunctionService") +public class HelperFunctionsImpl implements HelperFunctionService { + + @Override + public boolean isAuthorizedToMakeChange(String username) { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if(username.equalsIgnoreCase(authentication.getName()) || authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ADMIN"))){ + return true; + } else { + throw new EntityNotFoundException(authentication.getName() + " not authorized to make changes"); + } + } +} diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/RoleService.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/RoleService.java new file mode 100644 index 00000000..9ac14186 --- /dev/null +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/RoleService.java @@ -0,0 +1,9 @@ +package com.lambdaschool.shoppingcart.services; + +import com.lambdaschool.shoppingcart.models.Role; + +public interface RoleService { + + + Role findRoleById(long roleid); +} diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/RoleServiceImpl.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/RoleServiceImpl.java new file mode 100644 index 00000000..804661a3 --- /dev/null +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/RoleServiceImpl.java @@ -0,0 +1,21 @@ +package com.lambdaschool.shoppingcart.services; + +import com.lambdaschool.shoppingcart.exceptions.ResourceNotFoundException; +import com.lambdaschool.shoppingcart.models.Role; +import com.lambdaschool.shoppingcart.repositories.RoleRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service(value = "roleService") +public class RoleServiceImpl implements RoleService{ + + @Autowired + RoleRepository rolerepos; + + @Override + public Role findRoleById(long roleid) { + Role role = rolerepos.findById(roleid) + .orElseThrow(() -> new ResourceNotFoundException("Role" + roleid + " not found!")); + return role; + } +} diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/SecurityUserServiceImpl.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/SecurityUserServiceImpl.java new file mode 100644 index 00000000..5b026788 --- /dev/null +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/SecurityUserServiceImpl.java @@ -0,0 +1,29 @@ +package com.lambdaschool.shoppingcart.services; + +import com.lambdaschool.shoppingcart.exceptions.ResourceNotFoundException; +import com.lambdaschool.shoppingcart.models.User; +import com.lambdaschool.shoppingcart.repositories.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service(value = "securityUserService") +public class SecurityUserServiceImpl implements UserDetailsService { + + @Autowired + private UserRepository userrepos; + + @Transactional + @Override + public UserDetails loadUserByUsername(String s) throws ResourceNotFoundException { + User user = userrepos.findByUsername(s.toLowerCase()); + if (user == null) + { + throw new ResourceNotFoundException("Invalid username or password"); + } + return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), user.getAuthority()); + } +} diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/UserAuditing.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/UserAuditing.java index d833c576..d71d36cc 100644 --- a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/UserAuditing.java +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/UserAuditing.java @@ -1,6 +1,8 @@ package com.lambdaschool.shoppingcart.services; import org.springframework.data.domain.AuditorAware; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import java.util.Optional; @@ -22,7 +24,12 @@ public class UserAuditing public Optional getCurrentAuditor() { String uname; - uname = "SYSTEM"; + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if(authentication != null) { + uname = authentication.getName(); + } else { + uname = "SYSTEM"; + } return Optional.of(uname); } } diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/UserService.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/UserService.java index 201af026..45575b94 100644 --- a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/UserService.java +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/UserService.java @@ -40,4 +40,7 @@ public interface UserService * @return the saved user object including any automatically generated fields */ User save(User user); + + + User findByName(String name); } diff --git a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/UserServiceImpl.java b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/UserServiceImpl.java index 6b7a9047..51c6eb8d 100644 --- a/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/UserServiceImpl.java +++ b/shoppingcart/src/main/java/com/lambdaschool/shoppingcart/services/UserServiceImpl.java @@ -2,7 +2,9 @@ import com.lambdaschool.shoppingcart.exceptions.ResourceFoundException; import com.lambdaschool.shoppingcart.exceptions.ResourceNotFoundException; +import com.lambdaschool.shoppingcart.models.Role; import com.lambdaschool.shoppingcart.models.User; +import com.lambdaschool.shoppingcart.models.UserRoles; import com.lambdaschool.shoppingcart.repositories.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -25,6 +27,10 @@ public class UserServiceImpl @Autowired private CartService cartService; + @Autowired + private RoleService roleService; + + @Override public List findAll() { @@ -46,6 +52,17 @@ public User findUserById(long id) .orElseThrow(() -> new ResourceNotFoundException("User id " + id + " not found!")); } + @Override + public User findByName(String name) + { + User u = userrepos.findByUsername(name.toLowerCase()); + if(u == null) + { + throw new ResourceNotFoundException("User name " + name + " not found!"); + } + return u; + } + @Transactional @Override public void delete(long id) @@ -61,8 +78,22 @@ public User save(User user) { User newUser = new User(); + if (user.getUserid() != 0) { + userrepos.findById(user.getUserid()) + .orElseThrow(() -> new ResourceNotFoundException("User ID " + user.getUserid() + " was not found" + + ".")); + newUser.setUserid(user.getUserid()); + } + newUser.setUsername(user.getUsername()); newUser.setComments(user.getComments()); + newUser.setNoEncodePassword(user.getPassword()); + + for (UserRoles ur: user.getRoles()) { + + Role addRole = roleService.findRoleById(ur.getRole().getRoleid()); + newUser.getRoles().add(new UserRoles(newUser, addRole)); + } if (user.getCarts() .size() > 0) diff --git a/shoppingcart/src/main/resources/data.sql b/shoppingcart/src/main/resources/data.sql index a085e892..eef0c0ea 100644 --- a/shoppingcart/src/main/resources/data.sql +++ b/shoppingcart/src/main/resources/data.sql @@ -1,3 +1,46 @@ +-- DELETE +-- FROM cartitems; +-- +-- DELETE +-- FROM products; +-- +-- DELETE +-- FROM carts; +-- +-- DELETE +-- FROM users; +-- +-- INSERT INTO USERS(USERID, USERNAME, COMMENTS, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE) +-- VALUES (1, 'barnbarn', '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), +-- (2, 'cinnamon', '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), +-- (3, 'stumps', '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP); +-- +-- INSERT INTO PRODUCTS(PRODUCTID, NAME, DESCRIPTION, PRICE, COMMENTS, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE) +-- VALUES (1, 'PEN', 'MAKES WORDS', 2.50, '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), +-- (2, 'PENCIL', 'DOES MATH', 1.50, '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), +-- (3, 'COFFEE', 'EVERYONE NEEDS COFFEE', 4.00, '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP); +-- +-- INSERT INTO CARTS(CARTID, USERID, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE) +-- VALUES (1, 1, 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), +-- (2, 1, 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), +-- (3, 3, 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP); +-- +-- INSERT INTO CARTITEMS(CARTID, PRODUCTID, QUANTITY, COMMENTS, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE) +-- VALUES (1, 1, 4, '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), +-- (1, 2, 3, '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), +-- (1, 3, 2, '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), +-- (2, 3, 1, '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), +-- (3, 3, 17, '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP); + + +/* +We must tell hibernate the ids that have already been used. +The number must be larger than the last used id. +15 > 3 so we are good! + */ + +-- alter sequence hibernate_sequence restart with 15; + DELETE FROM cartitems; @@ -7,13 +50,29 @@ FROM products; DELETE FROM carts; +DELETE +FROM userroles; + DELETE FROM users; -INSERT INTO USERS(USERID, USERNAME, COMMENTS, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE) - VALUES (1, 'barnbarn', '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), - (2, 'cinnamon', '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), - (3, 'stumps', '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP); +DELETE +FROM roles; + +INSERT INTO USERS(USERID, USERNAME, PASSWORD, COMMENTS, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE) + VALUES (1, 'barnbarn', '$2y$12$3jkQBYZpeKKDSDA1Ws1uzuhIAztEnI8UyRZHQ98pTij7xxp6RtlI2', '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), + (2, 'cinnamon', '$2y$12$5EhoDOj2oGGEhmW8UFwh6e5an6WZ/IaoDPCux0oN4x4pwLm0pj6lq', '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), + (3, 'stumps', '$2y$12$1J5duOYDY4qZZfkOSQwSi.kps8UdatRiw835XN6TL4Vw6f6ioVFBW', '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP); + +INSERT INTO ROLES(ROLEID, NAME, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE) + VALUES (1, 'ADMIN', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), + (2, 'USER', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP); + +INSERT INTO USERROLES(USERID, ROLEID, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE) + VALUES (1, 1, 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), + (2, 1, 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), + (2, 2, 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), + (3, 2, 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP); INSERT INTO PRODUCTS(PRODUCTID, NAME, DESCRIPTION, PRICE, COMMENTS, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE) VALUES (1, 'PEN', 'MAKES WORDS', 2.50, '', 'SYSTEM', CURRENT_TIMESTAMP, 'SYSTEM', CURRENT_TIMESTAMP), @@ -40,3 +99,4 @@ The number must be larger than the last used id. */ alter sequence hibernate_sequence restart with 15; +