Commit bc47e412 authored by Khalid Ali's avatar Khalid Ali
Browse files

Merge branch 'feature/initial-checkin' into 'master'

Feature/initial checkin

See merge request !1
parents b425af1f 86a1440b
......@@ -14,6 +14,16 @@ plugins {
id "org.flywaydb.flyway" version "5.2.4"
}
plugins {
id "org.sonarqube" version "2.6"
}
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.8.2"
}
flyway {
url= "jdbc:postgresql://localhost:26257/testdb"
user= "user17"
......@@ -36,8 +46,16 @@ dependencies {
implementation('org.springframework.boot:spring-boot-starter-data-jpa')
implementation('org.springframework.boot:spring-boot-starter-data-rest')
implementation('org.springframework.boot:spring-boot-starter-web')
implementation('org.springframework.boot:spring-boot-starter-actuator')
implementation('com.fasterxml.jackson.dataformat:jackson-dataformat-xml')
implementation('com.fasterxml.jackson.datatype:jackson-datatype-joda')
implementation('org.springframework.security:spring-security-config')
implementation('org.modelmapper:modelmapper:2.3.1')
compile group: 'org.postgresql', name: 'postgresql', version: '42.2.5'
compile('org.springframework.security:spring-security-cas')
compile('org.springframework.security:spring-security-test')
compile('io.springfox:springfox-swagger2:2.9.2')
compile('io.springfox:springfox-swagger-ui:2.9.2')
compile('org.postgresql:postgresql:42.2.5')
compileOnly('org.projectlombok:lombok')
testImplementation('org.springframework.boot:spring-boot-starter-test')
testImplementation('org.assertj:assertj-core')
......
package com.gmu.bookshare;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
import org.jasig.cas.client.validation.TicketValidator;
import org.modelmapper.ModelMapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.context.event.EventListener;
import org.springframework.core.Ordered;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.filter.ForwardedHeaderFilter;
import javax.servlet.http.HttpSessionEvent;
@SpringBootApplication
public class BookshareApplication {
......@@ -16,4 +35,85 @@ public class BookshareApplication {
public ModelMapper modelMapper() {
return new ModelMapper();
}
@Bean
FilterRegistrationBean forwardedHeaderFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new ForwardedHeaderFilter());
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegistrationBean;
}
@Bean
public ServiceProperties serviceProperties() {
ServiceProperties serviceProperties = new ServiceProperties();
serviceProperties.setService("https://localhost:9090/login/cas");
serviceProperties.setSendRenew(false);
return serviceProperties;
}
@Bean
@Primary
public AuthenticationEntryPoint authenticationEntryPoint(
ServiceProperties sP) {
// URL where user will be redirected to for authentication
CasAuthenticationEntryPoint entryPoint
= new CasAuthenticationEntryPoint();
entryPoint.setLoginUrl("https://localhost:9443/login");
entryPoint.setServiceProperties(sP);
return entryPoint;
}
/**
* Validates service ticket given to user upon authentication.
*
* @return TicketValidator object
*/
@Bean
public TicketValidator ticketValidator() {
return new Cas30ServiceTicketValidator(
"https://localhost:9443/");
}
@Bean
public CasAuthenticationProvider casAuthenticationProvider() {
CasAuthenticationProvider provider = new CasAuthenticationProvider();
provider.setServiceProperties(serviceProperties());
provider.setTicketValidator(ticketValidator());
provider.setUserDetailsService(
s -> new User("casuser", "Mellon", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_ADMIN")));
provider.setKey("CAS_PROVIDER_LOCALHOST_9000");
return provider;
}
@Bean
public SecurityContextLogoutHandler securityContextLogoutHandler() {
return new SecurityContextLogoutHandler();
}
@Bean
public LogoutFilter logoutFilter() {
LogoutFilter logoutFilter = new LogoutFilter(
"https://localhost:9443/logout",
securityContextLogoutHandler());
logoutFilter.setFilterProcessesUrl("/logout/cas");
return logoutFilter;
}
@Bean
public SingleSignOutFilter singleSignOutFilter() {
SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
singleSignOutFilter.setCasServerUrlPrefix("https://localhost:9443");
singleSignOutFilter.setIgnoreInitConfiguration(true);
return singleSignOutFilter;
}
@EventListener
public SingleSignOutHttpSessionListener singleSignOutHttpSessionListener(
HttpSessionEvent event) {
return new SingleSignOutHttpSessionListener();
}
}
package com.gmu.bookshare.beer;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Data
@NoArgsConstructor
@Entity
class Beer {
public Beer(String name) {
this.name = name;
}
@Id
@GeneratedValue
private Long id;
@NonNull
private String name;
}
\ No newline at end of file
package com.gmu.bookshare.beer;
import org.springframework.stereotype.Component;
@Component
public class BeerCommandLineRunner {//implements CommandLineRunner {
// private final BeerRepository repository;
//
// public BeerCommandLineRunner(BeerRepository repository) {
// this.repository = repository;
// }
//
// @Override
// public void run(String... strings) throws Exception {
// // Top beers from https://www.beeradvocate.com/lists/us, November 2018
// Stream.of("Kentucky Brunch Brand Stout", "Marshmallow Handjee", "Barrel-Aged Abraxas",
// "Hunahpu's Imperial Stout", "King Julius", "Heady Topper",
// "Budweiser", "Coors Light", "PBR").forEach(name ->
// repository.save(new Beer(name))
// );
// repository.findAll().forEach(System.out::println);
// }
}
\ No newline at end of file
package com.gmu.bookshare.beer;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
import java.util.stream.Collectors;
@RestController
public class BeerController {
private BeerRepository repository;
public BeerController(BeerRepository repository) {
this.repository = repository;
}
@GetMapping("/good-beers")
@CrossOrigin(origins = "http://localhost:8081")
public Collection<Beer> goodBeers() {
return repository.findAll().stream()
.filter(this::isGreat)
.collect(Collectors.toList());
}
private boolean isGreat(Beer beer) {
return !beer.getName().equals("Budweiser") &&
!beer.getName().equals("Coors Light") &&
!beer.getName().equals("PBR");
}
}
\ No newline at end of file
package com.gmu.bookshare.beer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
@RepositoryRestResource
interface BeerRepository extends JpaRepository<Beer, Long> {
}
\ No newline at end of file
package com.gmu.bookshare.config;
import org.jasig.cas.client.session.SingleSignOutFilter;
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.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import java.util.Collections;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private AuthenticationProvider authenticationProvider;
private AuthenticationEntryPoint authenticationEntryPoint;
private SingleSignOutFilter singleSignOutFilter;
private LogoutFilter logoutFilter;
@Autowired
public SecurityConfig(CasAuthenticationProvider casAuthenticationProvider, AuthenticationEntryPoint eP,
LogoutFilter lF, SingleSignOutFilter ssF) {
this.authenticationProvider = casAuthenticationProvider;
this.authenticationEntryPoint = eP;
this.logoutFilter = lF;
this.singleSignOutFilter = ssF;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.regexMatchers("/secured.*", "/login", "/bs/api/.*")
.authenticated()
.and()
.authorizeRequests()
.regexMatchers("/")
.permitAll()
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.logout().logoutSuccessUrl("/bs/api/logout")
.and()
.addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class)
.addFilterBefore(logoutFilter, LogoutFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return new ProviderManager(Collections.singletonList(authenticationProvider));
}
@Bean
public CasAuthenticationFilter casAuthenticationFilter(ServiceProperties sP) throws Exception {
CasAuthenticationFilter filter = new CasAuthenticationFilter();
filter.setServiceProperties(sP);
filter.setAuthenticationManager(authenticationManager());
return filter;
}
}
\ No newline at end of file
package com.gmu.bookshare.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}
package com.gmu.bookshare.entity;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.Date;
......@@ -9,10 +11,8 @@ import java.util.Date;
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "bid")
@Getter
@Setter
public class Bid {
@Table(name = "Bid")
public class BidEntity {
@Id
@GeneratedValue
......@@ -31,6 +31,31 @@ public class Bid {
@Column(name = "userId")
private Long userId;
@Column(name = "listingId")
private Long listingId;
// @ManyToMany(fetch = FetchType.LAZY,
// cascade = {
// CascadeType.PERSIST,
// CascadeType.MERGE
// },
// mappedBy = "posts")
// private Set<ListingEntity> posts = new HashSet<>();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "listingId")
private ListingEntity listing;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "shareUserId")
private ShareUser shareUserOwner;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BidEntity)) return false;
return id != null && id.equals(((BidEntity) o).id);
}
@Override
public int hashCode() {
return 31;
}
}
......@@ -4,15 +4,15 @@ import lombok.*;
import javax.persistence.*;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@Data
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
@Entity
@Getter
@Setter
@Table(name = "listing")
@Table(name = "Listing")
public class ListingEntity {
@Id
......@@ -48,15 +48,48 @@ public class ListingEntity {
@Column(name = "createDate")
private Date createDate;
@NonNull
@Column(name = "bid_id")
private Long bid_id;
@NonNull
@Column(name = "owner")
private Long owner;
@NonNull
@Column(name = "title")
private String title;
// @ManyToMany(fetch = FetchType.LAZY,
// cascade = {
// CascadeType.PERSIST,
// CascadeType.MERGE
// })
// @JoinTable(name = "listing2bids",
// joinColumns = { @JoinColumn(name = "listingId") },
// inverseJoinColumns = { @JoinColumn(name = "bidId") })
@OneToMany(
mappedBy = "listing",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private Set<BidEntity> bids = new HashSet<>();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "shareUserId")
private ShareUser shareUser;
public void addBid(BidEntity bid) {
bids.add(bid);
bid.setListing(this);
}
public void removeBid(BidEntity bid) {
bids.remove(bid);
bid.setListing(null);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ListingEntity)) return false;
return id != null && id.equals(((ListingEntity) o).id);
}
@Override
public int hashCode() {
return 41;
}
}
package com.gmu.bookshare.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.*;
import javax.persistence.*;
import java.util.Set;
@Data
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "user")
@Getter
@Table(name = "ShareUser")
public class ShareUser {
@Id
......@@ -20,9 +18,39 @@ public class ShareUser {
@Column(name = "id", updatable = false)
private Long id;
@NonNull
@Column(name = "email")
private String email;
@NonNull
@Column(name = "name")
private String name;
@NonNull
@OneToMany(mappedBy = "shareUser")
private Set<ListingEntity> listingsOwned;
@NonNull
@OneToMany(mappedBy = "shareUserOwner")
private Set<BidEntity> bidsOwned;
public void addBid(BidEntity bid) {
bidsOwned.add(bid);
bid.setShareUserOwner(this);
}
public void removeBid(BidEntity bid) {
bidsOwned.remove(bid);
bid.setShareUserOwner(null);
}
public void addListing(ListingEntity listing) {
listingsOwned.add(listing);
listing.setShareUser(this);
}
public void removeListing(ListingEntity listing) {
listingsOwned.remove(listing);
listing.setShareUser(null);
}
}
package com.gmu.bookshare.model;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.util.Date;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class BidDto {
@Id
@GeneratedValue
@JsonProperty("id")
private Long id;
@JsonProperty("createDate")
private Date createDate;
@JsonProperty("price")
private double price;
@JsonProperty("flag")
private int flagged;
@JsonProperty("userId")
private Long userId;
}
package com.gmu.bookshare.model;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.NoArgsConstructor;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
@Data
@Getter