Skip to content

mvp #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

mvp #16

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions shoppingcart/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,24 @@
<version>2.9.2</version>
</dependency>
<!-- Swagger Dependencies End -->
<!--Security - once added, system wont work until security is set up-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!--#Security test-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.6.RELEASE</version>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
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
{
private static String CLIENT_ID = System.getenv("OAUTHCLIENTID");
private static String CLIENT_SECRET = System.getenv("OAUTHCLIENTSECRET");

private static String GRANT_TYPE_PASSWORD = "password";
private static String AUTHORIZATION_CODE = "authorization_code";
private static String SCOPE_READ = "read";
private static String SCOPE_WRITE = "write";
private static String SCOPE_TRUST = "trust";
private static 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,SCOPE_TRUST)
.accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS);
}

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception
{
endpoints.tokenStore(tokenStore).authenticationManager(authenticationManager);

endpoints.pathMapping("/oauth/token", "/login");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
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 String RESOURCE_ID = "resource_id";
@Override
public void configure (ResourceServerSecurityConfigurer resources)
{
resources.resourceId(RESOURCE_ID)
.stateless(false);
}
@Override
public void configure (HttpSecurity http) throws Exception
{
// who has access to what
http.authorizeRequests()
.antMatchers("/",
"/h2-console/**",
"/swagger-resources/**",
"/swagger-resource/**",
"/swagger-ui.html",
"/v2/api-docs",
"/webjars/**",
"/createnewuser")
.permitAll()
.antMatchers("/users/**")
.hasAnyRole("ADMIN")
.antMatchers("/roles/**")
.hasAnyRole("ADMIN")
.antMatchers("/logout")
.authenticated()
.antMatchers("/carts/**")
.authenticated()
.antMatchers("/products/**")
.hasAnyRole("ADMIN")
.anyRequest().denyAll()
.and()
.exceptionHandling()
.accessDeniedHandler(new OAuth2AccessDeniedHandler());
http.csrf().disable();
http.headers().frameOptions().disable(); // required by H2
http.logout().disable();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
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.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;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
@Bean
protected AuthenticationManager authenticationManager() throws Exception
{
return super.authenticationManager();
}

@Autowired
private UserDetailsService securityUserService;

@Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(securityUserService).passwordEncoder(encoder());
}

@Bean
public TokenStore tokenStore()
{
return new InMemoryTokenStore();
}

@Bean
public PasswordEncoder encoder()
{
return new BCryptPasswordEncoder();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

@RestController
Expand All @@ -19,40 +20,46 @@ public class CartController
@Autowired
private UserService userService;

@GetMapping(value = "/user/{userid}",
@GetMapping(value = "/user",
produces = {"application/json"})
public ResponseEntity<?> listCartItemsByUserId(
@PathVariable
long userid)
public ResponseEntity<?> listCartItemsByUserId()
{
User u = userService.findUserById(userid);
String currentUserName = SecurityContextHolder.getContext()
.getAuthentication()
.getName();
User u = userService.findByName(currentUserName);
return new ResponseEntity<>(u,
HttpStatus.OK);
}

@PutMapping(value = "/add/user/{userid}/product/{productid}",
@PutMapping(value = "/add/product/{productid}",
produces = {"application/json"})
public ResponseEntity<?> addToCart(
@PathVariable
long userid,
@PathVariable
long productid)
{
CartItem addCartTtem = cartItemService.addToCart(userid,
String currentUserName = SecurityContextHolder.getContext()
.getAuthentication()
.getName();
long userid = userService.findByName(currentUserName).getUserid();

CartItem addCartItem = cartItemService.addToCart(userid,
productid,
"I am not working");
return new ResponseEntity<>(addCartTtem,
return new ResponseEntity<>(addCartItem,
HttpStatus.OK);
}

@DeleteMapping(value = "/remove/user/{userid}/product/{productid}",
@DeleteMapping(value = "/remove/product/{productid}",
produces = {"application/json"})
public ResponseEntity<?> removeFromCart(
@PathVariable
long userid,
@PathVariable
long productid)
{
String currentUserName = SecurityContextHolder.getContext()
.getAuthentication()
.getName();
long userid = userService.findByName(currentUserName).getUserid();
CartItem removeCartItem = cartItemService.removeFromCart(userid,
productid,
"I am still not working");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

Expand Down Expand Up @@ -194,6 +195,7 @@ public ResponseEntity<?> updateUser(
* @param id the primary key of the user you wish to delete
* @return Status of OK
*/
@PreAuthorize(value = "hasAnyRole('ADMIN')")
@DeleteMapping(value = "/user/{id}")
public ResponseEntity<?> deleteUserById(
@PathVariable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package com.lambdaschool.shoppingcart.models;

import com.fasterxml.jackson.annotation.JsonIgnore;
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.*;
import javax.validation.constraints.Email;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
Expand Down Expand Up @@ -163,14 +168,20 @@ public String getPassword()
return password;
}

public void setPasswordNoEncrypt(String password)
{
this.password = password;
}

/**
* Setter for password
*
* @param password the new password (String) for the user
*/
public void setPassword(String password)
{
this.password = password;
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
this.password = passwordEncoder.encode(password);
}

/**
Expand Down Expand Up @@ -212,4 +223,16 @@ public void setCarts(Set<CartItem> carts)
{
this.carts = carts;
}

@JsonIgnore
public List<SimpleGrantedAuthority> getAuthority()
{
List<SimpleGrantedAuthority> rtnList = new ArrayList<>();
for (UserRoles r : this.roles)
{
String myRole = "ROLE_" + r.getRole().getName().toUpperCase();
rtnList.add(new SimpleGrantedAuthority(myRole));
}
return rtnList;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.lambdaschool.shoppingcart.services;

import com.lambdaschool.shoppingcart.exceptions.ResourceNotFoundException;
import com.lambdaschool.shoppingcart.models.User;
import com.lambdaschool.shoppingcart.repository.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 UsernameNotFoundException
{
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());
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
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;

/**
* Spring Boot needs to know what username to use for the auditing fields CreatedBy and ModifiedBy
* For now, a default name will be used
* Checks to see if there is an authenticated user. If so use that user,
* if not which happens when seeding the database, use a default value
*/
@Component
public class UserAuditing
Expand All @@ -22,7 +23,15 @@ public class UserAuditing
public Optional<String> getCurrentAuditor()
{
String uname;
uname = "SYSTEM";
Authentication authentication = SecurityContextHolder.getContext()
.getAuthentication();
if (authentication != null)
{
uname = authentication.getName();
} else
{
uname = "SYSTEM";
}
return Optional.of(uname);
}
}
}
Loading