diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1bd77ee --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3.8' +services: + db: + image: mysql + command: --default-authentication-plugin=mysql_native_password + ports: + - 3306:3306 + environment: + MYSQL_ROOT_PASSWORD: password + phpmyadmin: + image: phpmyadmin + restart: always + ports: + - 9000:80 + environment: + PMA_HOST: db + MYSQL_ROOT_PASSWORD: password \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5740010..f771d8b 100644 --- a/pom.xml +++ b/pom.xml @@ -50,8 +50,67 @@ spring-security-test test + + org.mapstruct + mapstruct + 1.4.2.Final + + + + org.mapstruct + mapstruct-processor + 1.4.2.Final + provided + + + org.springframework.mobile + spring-mobile-device + 2.0.0.M3 + + + + io.jsonwebtoken + jjwt + 0.9.1 + + + com.google.cloud + google-cloud-storage + 2.3.0 + + + + public report + Maven Center + https://repo.maven.apache.org/maven2/ + + + graphql date repo + repo for date of graph ql + https://dl.bintray.com/donbeave/maven/ + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + true + + + + jcenter + https://jcenter.bintray.com/ + + + spring-snapshots + https://repo.spring.io/snapshot + + true + + + @@ -66,7 +125,21 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + 16 + 16 + + - + + + repository.spring.release + Spring GA Repository + https://repo.spring.io/plugins-release/ + + diff --git a/src/main/java/se/project/coalingot/CoalingotApplication.java b/src/main/java/se/project/coalingot/CoalingotApplication.java index 90b4f5d..883252c 100644 --- a/src/main/java/se/project/coalingot/CoalingotApplication.java +++ b/src/main/java/se/project/coalingot/CoalingotApplication.java @@ -2,6 +2,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @SpringBootApplication public class CoalingotApplication { @@ -9,5 +12,17 @@ public class CoalingotApplication { public static void main(String[] args) { SpringApplication.run(CoalingotApplication.class, args); } + @Bean + public WebMvcConfigurer corsConfigurer(){ + return new WebMvcConfigurer() { + @Override + public void addCorsMappings(CorsRegistry registry){ + registry.addMapping("/**") + .allowedOrigins("http://localhost:3000") + .allowedOrigins("https://firebase.hosting.app.somehting") + .exposedHeaders("x-total-count"); + } + }; + } } diff --git a/src/main/java/se/project/coalingot/auction/controller/AuctionController.java b/src/main/java/se/project/coalingot/auction/controller/AuctionController.java new file mode 100644 index 0000000..ee1eb24 --- /dev/null +++ b/src/main/java/se/project/coalingot/auction/controller/AuctionController.java @@ -0,0 +1,7 @@ +package se.project.coalingot.auction.controller; + +import org.springframework.stereotype.Controller; + +@Controller +public class AuctionController { +} diff --git a/src/main/java/se/project/coalingot/auction/dao/AuctionDao.java b/src/main/java/se/project/coalingot/auction/dao/AuctionDao.java new file mode 100644 index 0000000..0db2dd7 --- /dev/null +++ b/src/main/java/se/project/coalingot/auction/dao/AuctionDao.java @@ -0,0 +1,4 @@ +package se.project.coalingot.auction.dao; + +public interface AuctionDao { +} diff --git a/src/main/java/se/project/coalingot/auction/dao/AuctionDaoImpl.java b/src/main/java/se/project/coalingot/auction/dao/AuctionDaoImpl.java new file mode 100644 index 0000000..44db286 --- /dev/null +++ b/src/main/java/se/project/coalingot/auction/dao/AuctionDaoImpl.java @@ -0,0 +1,7 @@ +package se.project.coalingot.auction.dao; + +import org.springframework.stereotype.Repository; + +@Repository +public class AuctionDaoImpl implements AuctionDao{ +} diff --git a/src/main/java/se/project/coalingot/auction/dto/AuctionDto.java b/src/main/java/se/project/coalingot/auction/dto/AuctionDto.java new file mode 100644 index 0000000..a2adeee --- /dev/null +++ b/src/main/java/se/project/coalingot/auction/dto/AuctionDto.java @@ -0,0 +1,24 @@ +package se.project.coalingot.auction.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import se.project.coalingot.item.dto.ItemAuctionDto; + +import java.util.Date; +import java.util.List; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AuctionDto { + Long auctionId; + ItemAuctionDto auctionItem; + Double highestPrice; + Boolean status; + Date startDate; + Date endDate; + List histories; +} diff --git a/src/main/java/se/project/coalingot/auction/dto/AuctionHistoryDto.java b/src/main/java/se/project/coalingot/auction/dto/AuctionHistoryDto.java new file mode 100644 index 0000000..37a0447 --- /dev/null +++ b/src/main/java/se/project/coalingot/auction/dto/AuctionHistoryDto.java @@ -0,0 +1,23 @@ +package se.project.coalingot.auction.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import se.project.coalingot.auctionuser.dto.AuctionUserPaticipantDto; +import se.project.coalingot.item.dto.ItemAuctionDto; +import se.project.coalingot.item.dto.ItemDto; +import se.project.coalingot.item.dto.ItemHistoryDto; + +import java.util.Date; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AuctionHistoryDto { + AuctionUserPaticipantDto auctionUser; + Double submitPrice; + Date submitAt; + ItemHistoryDto auctionItem; +} diff --git a/src/main/java/se/project/coalingot/auction/entity/Auction.java b/src/main/java/se/project/coalingot/auction/entity/Auction.java new file mode 100644 index 0000000..37e378a --- /dev/null +++ b/src/main/java/se/project/coalingot/auction/entity/Auction.java @@ -0,0 +1,35 @@ +package se.project.coalingot.auction.entity; + +import lombok.*; +import se.project.coalingot.item.entity.Item; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@Data +@Builder +@Entity +@AllArgsConstructor +@NoArgsConstructor +public class Auction { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @EqualsAndHashCode.Exclude + Long auctionId; + + @OneToOne + Item auctionItem; + + @OneToMany(mappedBy = "auctionEvent") + List histories = new ArrayList<>(); + + Double highestPrice; + + Boolean status; + + Date startDate; + + Date endDate; +} diff --git a/src/main/java/se/project/coalingot/auction/entity/AuctionHistory.java b/src/main/java/se/project/coalingot/auction/entity/AuctionHistory.java new file mode 100644 index 0000000..fb0fbcb --- /dev/null +++ b/src/main/java/se/project/coalingot/auction/entity/AuctionHistory.java @@ -0,0 +1,30 @@ +package se.project.coalingot.auction.entity; + +import lombok.*; +import se.project.coalingot.auctionuser.entity.AuctionUser; +import se.project.coalingot.item.entity.Item; + +import javax.persistence.*; +import java.util.Date; + +@Data +@Builder +@Entity +@AllArgsConstructor +@NoArgsConstructor +public class AuctionHistory { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @EqualsAndHashCode.Exclude + Long auctionHistoryId; + + @ManyToOne + AuctionUser auctionUser; + + @ManyToOne + Auction auctionEvent; + + Double submitPrice; + + Date submitAt; +} diff --git a/src/main/java/se/project/coalingot/auction/entity/AuctionRequest.java b/src/main/java/se/project/coalingot/auction/entity/AuctionRequest.java new file mode 100644 index 0000000..13336c8 --- /dev/null +++ b/src/main/java/se/project/coalingot/auction/entity/AuctionRequest.java @@ -0,0 +1,16 @@ +package se.project.coalingot.auction.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AuctionRequest { + Long auctionId; + Long userId; + Double submitPrice; +} diff --git a/src/main/java/se/project/coalingot/auction/repository/AuctionHistoryRepository.java b/src/main/java/se/project/coalingot/auction/repository/AuctionHistoryRepository.java new file mode 100644 index 0000000..88c3ad4 --- /dev/null +++ b/src/main/java/se/project/coalingot/auction/repository/AuctionHistoryRepository.java @@ -0,0 +1,7 @@ +package se.project.coalingot.auction.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import se.project.coalingot.auction.entity.AuctionHistory; + +public interface AuctionHistoryRepository extends JpaRepository { +} diff --git a/src/main/java/se/project/coalingot/auction/repository/AuctionRepository.java b/src/main/java/se/project/coalingot/auction/repository/AuctionRepository.java new file mode 100644 index 0000000..55dfbef --- /dev/null +++ b/src/main/java/se/project/coalingot/auction/repository/AuctionRepository.java @@ -0,0 +1,7 @@ +package se.project.coalingot.auction.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import se.project.coalingot.auction.entity.Auction; + +public interface AuctionRepository extends JpaRepository { +} diff --git a/src/main/java/se/project/coalingot/auction/service/AuctionService.java b/src/main/java/se/project/coalingot/auction/service/AuctionService.java new file mode 100644 index 0000000..9e80dc2 --- /dev/null +++ b/src/main/java/se/project/coalingot/auction/service/AuctionService.java @@ -0,0 +1,4 @@ +package se.project.coalingot.auction.service; + +public interface AuctionService { +} diff --git a/src/main/java/se/project/coalingot/auction/service/AuctionServiceImpl.java b/src/main/java/se/project/coalingot/auction/service/AuctionServiceImpl.java new file mode 100644 index 0000000..f2a1db9 --- /dev/null +++ b/src/main/java/se/project/coalingot/auction/service/AuctionServiceImpl.java @@ -0,0 +1,7 @@ +package se.project.coalingot.auction.service; + +import org.springframework.stereotype.Service; + +@Service +public class AuctionServiceImpl implements AuctionService{ +} diff --git a/src/main/java/se/project/coalingot/auctionuser/controller/AuctionUserController.java b/src/main/java/se/project/coalingot/auctionuser/controller/AuctionUserController.java new file mode 100644 index 0000000..baf52df --- /dev/null +++ b/src/main/java/se/project/coalingot/auctionuser/controller/AuctionUserController.java @@ -0,0 +1,53 @@ +package se.project.coalingot.auctionuser.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +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.RequestBody; +import se.project.coalingot.auction.entity.Auction; +import se.project.coalingot.auction.entity.AuctionRequest; +import se.project.coalingot.auction.repository.AuctionRepository; +import se.project.coalingot.auctionuser.entity.AuctionUser; +import se.project.coalingot.auctionuser.service.AuctionUserService; +import se.project.coalingot.util.AuctionMapper; + +import java.util.List; + +@Controller +public class AuctionUserController { + @Autowired + AuctionUserService auctionUserService; + + // will change later + @Autowired + AuctionRepository auctionRepository; + + @PostMapping("/submit-price") + public ResponseEntity submitPrice( + @RequestBody AuctionRequest auctionRequest + ) { + auctionUserService.submitPrice( + auctionRequest.getAuctionId(), + auctionRequest.getUserId(), + auctionRequest.getSubmitPrice() + ); + return ResponseEntity.ok("You has been submitted the price."); + } + + @GetMapping("/see-all-auction") + public ResponseEntity seeAuction(){ + List output = auctionRepository.findAll(); + return ResponseEntity.ok(AuctionMapper.INSTANCE.seeAuction(output)); + } + + @GetMapping("auctionList/{auctionUserID}") + public ResponseEntity getAuctionThatSubmit( + @PathVariable("auctionUserID") Long auctionID + ) { + AuctionUser output = auctionUserService.getAuctionUser(auctionID); + return ResponseEntity.ok(AuctionMapper.INSTANCE.getAuctionUserDto(output)); + } +} \ No newline at end of file diff --git a/src/main/java/se/project/coalingot/auctionuser/dao/AuctionUserDao.java b/src/main/java/se/project/coalingot/auctionuser/dao/AuctionUserDao.java new file mode 100644 index 0000000..b73ac7c --- /dev/null +++ b/src/main/java/se/project/coalingot/auctionuser/dao/AuctionUserDao.java @@ -0,0 +1,8 @@ +package se.project.coalingot.auctionuser.dao; + +import se.project.coalingot.auctionuser.entity.AuctionUser; + +public interface AuctionUserDao { + void submitPrice(Long auctionId,Long userId,Double price); + AuctionUser getAuctionUser(Long auctionUserID); +} diff --git a/src/main/java/se/project/coalingot/auctionuser/dao/AuctionUserDaoImpl.java b/src/main/java/se/project/coalingot/auctionuser/dao/AuctionUserDaoImpl.java new file mode 100644 index 0000000..33f715b --- /dev/null +++ b/src/main/java/se/project/coalingot/auctionuser/dao/AuctionUserDaoImpl.java @@ -0,0 +1,53 @@ +package se.project.coalingot.auctionuser.dao; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; +import se.project.coalingot.auction.entity.Auction; +import se.project.coalingot.auction.entity.AuctionHistory; +import se.project.coalingot.auction.repository.AuctionHistoryRepository; +import se.project.coalingot.auction.repository.AuctionRepository; +import se.project.coalingot.auctionuser.entity.AuctionUser; +import se.project.coalingot.auctionuser.repository.AuctionUserRepository; +import se.project.coalingot.item.entity.Item; +import se.project.coalingot.item.service.ItemService; + +import java.sql.Timestamp; +import java.time.LocalDateTime; + +@Repository +public class AuctionUserDaoImpl implements AuctionUserDao{ + @Autowired + ItemService itemService; + + @Autowired + AuctionRepository auctionRepository; + + @Autowired + AuctionUserRepository auctionUserRepository; + + @Autowired + AuctionHistoryRepository auctionHistoryRepository; + + @Override + public void submitPrice(Long auctionId,Long userId, Double price) { + AuctionUser auctionUser = auctionUserRepository.findById(userId).orElse(null); + Auction auction = auctionRepository.findById(auctionId).orElse(null); + if(price > auction.getHighestPrice()){ + auction.setHighestPrice(price); + auctionRepository.save(auction); + } + auctionHistoryRepository.save( + AuctionHistory.builder() + .auctionEvent(auction) + .auctionUser(auctionUser) + .submitPrice(price) + .submitAt(Timestamp.valueOf(LocalDateTime.now())) + .build() + ); + } + + @Override + public AuctionUser getAuctionUser(Long auctionUserID) { + return auctionUserRepository.findById(auctionUserID).orElse(null); + } +} diff --git a/src/main/java/se/project/coalingot/auctionuser/dto/AuctionUserDto.java b/src/main/java/se/project/coalingot/auctionuser/dto/AuctionUserDto.java new file mode 100644 index 0000000..ea996e9 --- /dev/null +++ b/src/main/java/se/project/coalingot/auctionuser/dto/AuctionUserDto.java @@ -0,0 +1,26 @@ +package se.project.coalingot.auctionuser.dto; + +import com.sun.istack.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import se.project.coalingot.auction.dto.AuctionHistoryDto; +import se.project.coalingot.auction.entity.AuctionHistory; +import se.project.coalingot.item.dto.ItemDto; + +import javax.persistence.Column; +import java.util.List; + +// user details +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AuctionUserDto { + String username; + String firstname; + String lastname; + List own; + List history; +} diff --git a/src/main/java/se/project/coalingot/auctionuser/dto/AuctionUserPaticipantDto.java b/src/main/java/se/project/coalingot/auctionuser/dto/AuctionUserPaticipantDto.java new file mode 100644 index 0000000..a2d6c9e --- /dev/null +++ b/src/main/java/se/project/coalingot/auctionuser/dto/AuctionUserPaticipantDto.java @@ -0,0 +1,15 @@ +package se.project.coalingot.auctionuser.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AuctionUserPaticipantDto { + String username; + String email; +} diff --git a/src/main/java/se/project/coalingot/auctionuser/entity/AuctionUser.java b/src/main/java/se/project/coalingot/auctionuser/entity/AuctionUser.java new file mode 100644 index 0000000..f0056bc --- /dev/null +++ b/src/main/java/se/project/coalingot/auctionuser/entity/AuctionUser.java @@ -0,0 +1,26 @@ +package se.project.coalingot.auctionuser.entity; + +import lombok.*; +import se.project.coalingot.auction.entity.Auction; +import se.project.coalingot.auction.entity.AuctionHistory; +import se.project.coalingot.item.entity.Item; +import se.project.coalingot.security.entity.User; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.OneToMany; +import java.util.ArrayList; +import java.util.List; + +@Data +@Entity +@AllArgsConstructor +@NoArgsConstructor +public class AuctionUser extends User { + @OneToMany(mappedBy = "ownBy",cascade= CascadeType.ALL) + List own = new ArrayList<>(); + + @OneToMany(mappedBy = "auctionUser",cascade= CascadeType.ALL) + List history = new ArrayList<>(); + +} diff --git a/src/main/java/se/project/coalingot/auctionuser/repository/AuctionUserRepository.java b/src/main/java/se/project/coalingot/auctionuser/repository/AuctionUserRepository.java new file mode 100644 index 0000000..4cb1b76 --- /dev/null +++ b/src/main/java/se/project/coalingot/auctionuser/repository/AuctionUserRepository.java @@ -0,0 +1,7 @@ +package se.project.coalingot.auctionuser.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import se.project.coalingot.auctionuser.entity.AuctionUser; + +public interface AuctionUserRepository extends JpaRepository { +} diff --git a/src/main/java/se/project/coalingot/auctionuser/service/AuctionUserService.java b/src/main/java/se/project/coalingot/auctionuser/service/AuctionUserService.java new file mode 100644 index 0000000..1b2ea7e --- /dev/null +++ b/src/main/java/se/project/coalingot/auctionuser/service/AuctionUserService.java @@ -0,0 +1,8 @@ +package se.project.coalingot.auctionuser.service; + +import se.project.coalingot.auctionuser.entity.AuctionUser; + +public interface AuctionUserService { + void submitPrice(Long auctionId,Long userId,Double price); + AuctionUser getAuctionUser(Long auctionUserID); +} diff --git a/src/main/java/se/project/coalingot/auctionuser/service/AuctionUserServiceImpl.java b/src/main/java/se/project/coalingot/auctionuser/service/AuctionUserServiceImpl.java new file mode 100644 index 0000000..bf5bf70 --- /dev/null +++ b/src/main/java/se/project/coalingot/auctionuser/service/AuctionUserServiceImpl.java @@ -0,0 +1,22 @@ +package se.project.coalingot.auctionuser.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import se.project.coalingot.auctionuser.dao.AuctionUserDao; +import se.project.coalingot.auctionuser.entity.AuctionUser; + +@Service +public class AuctionUserServiceImpl implements AuctionUserService{ + @Autowired + AuctionUserDao auctionUserDao; + + @Override + public void submitPrice(Long auctionId,Long userId, Double price) { + auctionUserDao.submitPrice(auctionId,userId,price); + } + + @Override + public AuctionUser getAuctionUser(Long auctionUserID) { + return auctionUserDao.getAuctionUser(auctionUserID); + } +} diff --git a/src/main/java/se/project/coalingot/config/AuctionCoreFilter.java b/src/main/java/se/project/coalingot/config/AuctionCoreFilter.java new file mode 100644 index 0000000..464ed2f --- /dev/null +++ b/src/main/java/se/project/coalingot/config/AuctionCoreFilter.java @@ -0,0 +1,39 @@ +package se.project.coalingot.config; + +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class AuctionCoreFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + Filter.super.init(filterConfig); + } + + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) req; + HttpServletResponse response = (HttpServletResponse) res; + + response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); + response.setHeader("Access-Control-Max-Age", "3600"); + response.setHeader("Access-Control-Allow-Headers", "*"); + + chain.doFilter(req, res); + } + + @Override + public void destroy() { + Filter.super.destroy(); + } +} \ No newline at end of file diff --git a/src/main/java/se/project/coalingot/config/InitApp.java b/src/main/java/se/project/coalingot/config/InitApp.java new file mode 100644 index 0000000..2d96874 --- /dev/null +++ b/src/main/java/se/project/coalingot/config/InitApp.java @@ -0,0 +1,124 @@ +package se.project.coalingot.config; + +import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; +import se.project.coalingot.auction.entity.Auction; +import se.project.coalingot.auction.repository.AuctionRepository; +import se.project.coalingot.auction.service.AuctionService; +import se.project.coalingot.auctionuser.entity.AuctionUser; +import se.project.coalingot.auctionuser.repository.AuctionUserRepository; +import se.project.coalingot.item.entity.Item; +import se.project.coalingot.item.repository.ItemRepository; +import se.project.coalingot.security.entity.Authority; +import se.project.coalingot.security.entity.AuthorityName; +import se.project.coalingot.security.repository.AuthorityRepository; + +import java.sql.Date; +import java.sql.Timestamp; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; + +@Component +public class InitApp implements ApplicationListener { + + PasswordEncoder encoder = new BCryptPasswordEncoder(); + + @Autowired + AuctionUserRepository auctionUserRepository; + + @Autowired + AuthorityRepository authorityRepository; + + @Autowired + ItemRepository itemRepository; + + @Autowired + AuctionRepository auctionRepository; + + @SneakyThrows + @Override + public void onApplicationEvent(ApplicationReadyEvent event) { + addUser(); + addItem(); + addAuction(); + } + + + AuctionUser newUser; + Item[] items = new Item[3]; + public void addUser() { + Authority roleUser = Authority.builder().name(AuthorityName.ROLE_USER).build(); + authorityRepository.save(roleUser); + + newUser = new AuctionUser(); + + newUser.setFirstname("Coal"); + newUser.setLastname("Ingot"); + newUser.setUsername("Coal123"); + newUser.setEmail("Coal@ingot.com"); + newUser.setPassword(encoder.encode("Ingot321")); + newUser.setEnabled(true); + newUser.setLastPasswordResetDate(Date.from(LocalDate.of(2021, 01, 01).atStartOfDay(ZoneId.systemDefault()).toInstant())); + + newUser.getAuthorities().add(roleUser); + auctionUserRepository.save(newUser); + } + + public void addItem() { + String[] image = { + "https://randomwordgenerator.com/img/picture-generator/52e2d64a4851a514f1dc8460962e33791c3ad6e04e507441722978d6944acc_640.jpg", + "https://randomwordgenerator.com/img/picture-generator/52e0dc404c5ab10ff3d8992cc12c30771037dbf85254784b772872dc944f_640.jpg", + "https://randomwordgenerator.com/img/picture-generator/54e8dd444253a514f1dc8460962e33791c3ad6e04e507440772872dc9344c6_640.jpg" + }; + for(int i=0;i<3;i++){ + items[i] = Item.builder() + .itemName("Item " + (i+1)) + .itemImage(image[i]) + .itemDescription("It is an item number " + (i + 1)) + .price(1.20) + .build(); + itemRepository.save( + items[i] + ); + } + } + + public void addAuction() { + Auction auc1 = Auction.builder() + .auctionItem(items[0]) + .startDate(Timestamp.valueOf(LocalDateTime.now())) + .endDate(Timestamp.valueOf(LocalDateTime.now())) + .highestPrice(1.50) + .status(false) + .build(); + items[0].setOwnBy(newUser); + itemRepository.save(items[0]); + auctionRepository.save(auc1); + + + Auction auc2 = Auction.builder() + .auctionItem(items[1]) + .startDate(Timestamp.valueOf(LocalDateTime.now())) + .endDate(Timestamp.valueOf(LocalDateTime.now())) + .highestPrice(1.50) + .status(true) + .build(); + auctionRepository.save(auc2); + + Auction auc3 = Auction.builder() + .auctionItem(items[2]) + .startDate(Timestamp.valueOf(LocalDateTime.now())) + .endDate(Timestamp.valueOf(LocalDateTime.now())) + .highestPrice(1.50) + .status(true) + .build(); + auctionRepository.save(auc3); + } + +} diff --git a/src/main/java/se/project/coalingot/config/WebSecurityConfig.java b/src/main/java/se/project/coalingot/config/WebSecurityConfig.java new file mode 100644 index 0000000..51fc5e4 --- /dev/null +++ b/src/main/java/se/project/coalingot/config/WebSecurityConfig.java @@ -0,0 +1,77 @@ +package se.project.coalingot.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +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.config.http.SessionCreationPolicy; +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.web.authentication.UsernamePasswordAuthenticationFilter; +import se.project.coalingot.security.controller.JwtAuthenticationEntryPoint; +import se.project.coalingot.security.controller.JwtAuthenticationTokenFilter; + +@Configuration +@EnableWebSecurity +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private JwtAuthenticationEntryPoint unauthorizedHandler; + + @Autowired + private UserDetailsService userDetailsService; + +// @Autowired +// public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { +// authenticationManagerBuilder +// .userDetailsService(this.userDetailsService) +// .passwordEncoder(passwordEncoder()); +// } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception { + return new JwtAuthenticationTokenFilter(); + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf().disable() + .cors().and() + .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + .authorizeRequests() + .antMatchers("/auth/**", "/refresh","/registers/**").permitAll() + .antMatchers(HttpMethod.POST,"/uploadFile").permitAll() + .antMatchers(HttpMethod.GET,"/items/**").hasRole("USER") + .antMatchers(HttpMethod.POST,"/items").hasRole("USER") + .anyRequest().authenticated(); + + // Custom JWT based security filter + http + .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); + + http.headers().frameOptions().disable(); + // disable page caching + http.headers().cacheControl(); + } + + +} diff --git a/src/main/java/se/project/coalingot/firebase/controller/BucketController.java b/src/main/java/se/project/coalingot/firebase/controller/BucketController.java new file mode 100644 index 0000000..35572c4 --- /dev/null +++ b/src/main/java/se/project/coalingot/firebase/controller/BucketController.java @@ -0,0 +1,24 @@ +package se.project.coalingot.firebase.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import se.project.coalingot.firebase.util.CloudStorageHelper; + +import javax.servlet.ServletException; +import java.io.IOException; + +@Controller +public class BucketController { + @Autowired + CloudStorageHelper cloudStorageHelper; + @PostMapping("/uploadFile") + public ResponseEntity uploadFile(@RequestPart(value = "file") + MultipartFile file) throws IOException, ServletException { + return ResponseEntity.ok(this.cloudStorageHelper.getImageUrl(file,"cmu-trp.appspot.com")); + } + +} diff --git a/src/main/java/se/project/coalingot/firebase/util/CloudStorageHelper.java b/src/main/java/se/project/coalingot/firebase/util/CloudStorageHelper.java new file mode 100644 index 0000000..8037cda --- /dev/null +++ b/src/main/java/se/project/coalingot/firebase/util/CloudStorageHelper.java @@ -0,0 +1,66 @@ +package se.project.coalingot.firebase.util; + +import org.springframework.stereotype.Component; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.cloud.storage.Acl; +import com.google.cloud.storage.BlobInfo; +import com.google.cloud.storage.Storage; +import com.google.cloud.storage.StorageOptions; +import org.springframework.core.io.ClassPathResource; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.ServletException; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; + +@Component +public class CloudStorageHelper { + private static Storage storage = null; + static { + InputStream serviceAccount = null; + try { + serviceAccount = new ClassPathResource("SE323.json").getInputStream(); + storage = StorageOptions.newBuilder() + .setCredentials(GoogleCredentials.fromStream(serviceAccount)) + .setProjectId("cmu-trp") + .build().getService(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public String uploadFile(MultipartFile filePart, final String bucketName) throws IOException { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HHmmssSSS"); + String dtString = sdf.format(new Date()); + final String fileName = dtString + "-" + filePart.getOriginalFilename(); + InputStream is = filePart.getInputStream(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + byte[] readBuf = new byte[4096]; + while (is.available() > 0) { + int byteRead = is.read(readBuf); + os.write(readBuf, 0, byteRead); + } + BlobInfo blobInfo = storage.create(BlobInfo.newBuilder(bucketName, fileName).setAcl(new ArrayList<>(Arrays.asList(Acl.of(Acl.User.ofAllUsers(),Acl.Role.READER)))) + .build(),os.toByteArray()); + return blobInfo.getMediaLink(); + } + public String getImageUrl(MultipartFile file, final String bucket) throws IOException, ServletException { + final String fileName = file.getOriginalFilename(); + if (fileName != null && !fileName.isEmpty() && fileName.contains(".")) { + final String extension = fileName.substring(fileName.lastIndexOf('.') + 1); + String[] allowedExt = {"jpg","jpeg","png","gif","JPG","JPEG","PNG","GIF"}; + for (String s : allowedExt) { + if (extension.equals(s)) { + return this.uploadFile(file, bucket); + } + } + throw new ServletException("file must be an image"); + } + return null; + } +} diff --git a/src/main/java/se/project/coalingot/item/controller/ItemController.java b/src/main/java/se/project/coalingot/item/controller/ItemController.java new file mode 100644 index 0000000..0781dba --- /dev/null +++ b/src/main/java/se/project/coalingot/item/controller/ItemController.java @@ -0,0 +1,50 @@ +package se.project.coalingot.item.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +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.RequestBody; +import se.project.coalingot.item.entity.Item; +import se.project.coalingot.item.entity.ItemRequest; +import se.project.coalingot.item.service.ItemService; +import se.project.coalingot.util.AuctionMapper; + +import java.util.List; + +@Controller +public class ItemController { + @Autowired + ItemService itemService; + + @GetMapping("/items") + public ResponseEntity getAllItems() { + List output = itemService.getAllItem(); + return ResponseEntity.ok(AuctionMapper.INSTANCE.getItemDto(output)); + } + + @GetMapping("/items/{itemId}") + public ResponseEntity getItem( + @PathVariable("itemId") Long itemId + ) { + Item output = itemService.itemDetail(itemId); + return ResponseEntity.ok(AuctionMapper.INSTANCE.getItemDto(output)); + } + + @PostMapping("/items") + public ResponseEntity postItem( + @RequestBody ItemRequest itemRequest + ){ + itemService.postItem(itemRequest); + return ResponseEntity.ok("Item has been posted"); + } + + @PostMapping("/items/end-acution/{auctionId}") + public ResponseEntity endAuction( + @PathVariable("auctionId") Long auctionId + ){ + return ResponseEntity.ok(AuctionMapper.INSTANCE.getItemDto(itemService.endAuction(auctionId))); + } +} diff --git a/src/main/java/se/project/coalingot/item/dao/ItemDao.java b/src/main/java/se/project/coalingot/item/dao/ItemDao.java new file mode 100644 index 0000000..1b59cb6 --- /dev/null +++ b/src/main/java/se/project/coalingot/item/dao/ItemDao.java @@ -0,0 +1,13 @@ +package se.project.coalingot.item.dao; + +import se.project.coalingot.item.entity.Item; +import se.project.coalingot.item.entity.ItemRequest; + +import java.util.List; + +public interface ItemDao { + List getAllItem(); + Item postItem(ItemRequest itemRequest); + Item itemDetail(Long id); + Item endAuction(Long id); +} diff --git a/src/main/java/se/project/coalingot/item/dao/ItemDaoImpl.java b/src/main/java/se/project/coalingot/item/dao/ItemDaoImpl.java new file mode 100644 index 0000000..5b536cd --- /dev/null +++ b/src/main/java/se/project/coalingot/item/dao/ItemDaoImpl.java @@ -0,0 +1,78 @@ +package se.project.coalingot.item.dao; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; +import se.project.coalingot.auction.entity.Auction; +import se.project.coalingot.auction.entity.AuctionHistory; +import se.project.coalingot.auction.repository.AuctionRepository; +import se.project.coalingot.auctionuser.entity.AuctionUser; +import se.project.coalingot.item.entity.Item; +import se.project.coalingot.item.entity.ItemRequest; +import se.project.coalingot.item.repository.ItemRepository; + +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.List; + +@Repository +public class ItemDaoImpl implements ItemDao { + @Autowired + ItemRepository itemRepository; + + @Autowired + AuctionRepository auctionRepository; + + @Override + public List getAllItem() { + return itemRepository.findAll(); + } + + @Override + public Item postItem(ItemRequest itemRequest) { + Item item = Item.builder() + .itemImage(itemRequest.getItemImage()) + .itemName(itemRequest.getItemName()) + .itemDescription(itemRequest.getItemDescription()) + .build(); + itemRepository.save(item); + + Auction auction = Auction.builder() + .auctionItem(item) + .startDate(Timestamp.valueOf(LocalDateTime.now())) + .endDate(itemRequest.getEndDate()) + .highestPrice(itemRequest.getStartPrice()) + .status(true) + .build(); + auctionRepository.save(auction); + + return item; + } + + @Override + public Item itemDetail(Long id) { + return itemRepository.findById(id).orElse(null); + } + + @Override + public Item endAuction(Long id) { + Auction auction = auctionRepository.findById(id).orElse(null); + List histories = auction.getHistories(); + Item item = auction.getAuctionItem(); + AuctionUser auctionUser = histories.get(0).getAuctionUser(); + + double maxPrice = histories.get(0).getSubmitPrice(); + for(int i=1;i maxPrice){ + maxPrice = histories.get(i).getSubmitPrice(); + auctionUser = histories.get(i).getAuctionUser(); + } + } + item.setOwnBy(auctionUser); + item.setPrice(maxPrice); + + auction.setStatus(false); + auctionRepository.save(auction); + + return itemRepository.save(item); + } +} diff --git a/src/main/java/se/project/coalingot/item/dto/ItemAuctionDto.java b/src/main/java/se/project/coalingot/item/dto/ItemAuctionDto.java new file mode 100644 index 0000000..cf0d160 --- /dev/null +++ b/src/main/java/se/project/coalingot/item/dto/ItemAuctionDto.java @@ -0,0 +1,17 @@ +package se.project.coalingot.item.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ItemAuctionDto { + Long itemId; + String itemName; + String itemImage; + String itemDescription; +} diff --git a/src/main/java/se/project/coalingot/item/dto/ItemDto.java b/src/main/java/se/project/coalingot/item/dto/ItemDto.java new file mode 100644 index 0000000..45a3149 --- /dev/null +++ b/src/main/java/se/project/coalingot/item/dto/ItemDto.java @@ -0,0 +1,20 @@ +package se.project.coalingot.item.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ItemDto { + Long itemId; + String itemName; + String itemImage; + String itemDescription; + Double price; + +} diff --git a/src/main/java/se/project/coalingot/item/dto/ItemHistoryDto.java b/src/main/java/se/project/coalingot/item/dto/ItemHistoryDto.java new file mode 100644 index 0000000..5c9d574 --- /dev/null +++ b/src/main/java/se/project/coalingot/item/dto/ItemHistoryDto.java @@ -0,0 +1,16 @@ +package se.project.coalingot.item.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ItemHistoryDto { + Long itemId; + String itemName; + String itemImage; +} diff --git a/src/main/java/se/project/coalingot/item/entity/Item.java b/src/main/java/se/project/coalingot/item/entity/Item.java new file mode 100644 index 0000000..eba57f9 --- /dev/null +++ b/src/main/java/se/project/coalingot/item/entity/Item.java @@ -0,0 +1,33 @@ +package se.project.coalingot.item.entity; + +import lombok.*; +import se.project.coalingot.auction.entity.Auction; +import se.project.coalingot.auction.entity.AuctionHistory; +import se.project.coalingot.auctionuser.entity.AuctionUser; + +import javax.persistence.*; +import java.util.Date; + +@Data +@Builder +@Entity +@AllArgsConstructor +@NoArgsConstructor +public class Item { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @EqualsAndHashCode.Exclude + Long itemId; + + String itemName; + String itemImage; + String itemDescription; + Double price; + + @ManyToOne(cascade= CascadeType.ALL) + AuctionUser ownBy; + + @OneToOne(mappedBy = "auctionItem") + Auction auctionAt; + +} diff --git a/src/main/java/se/project/coalingot/item/entity/ItemRequest.java b/src/main/java/se/project/coalingot/item/entity/ItemRequest.java new file mode 100644 index 0000000..36a69bf --- /dev/null +++ b/src/main/java/se/project/coalingot/item/entity/ItemRequest.java @@ -0,0 +1,20 @@ +package se.project.coalingot.item.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ItemRequest { + String itemName; + String itemImage; + String itemDescription; + Double startPrice; + Date endDate; +} diff --git a/src/main/java/se/project/coalingot/item/repository/ItemRepository.java b/src/main/java/se/project/coalingot/item/repository/ItemRepository.java new file mode 100644 index 0000000..e9ecbca --- /dev/null +++ b/src/main/java/se/project/coalingot/item/repository/ItemRepository.java @@ -0,0 +1,7 @@ +package se.project.coalingot.item.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import se.project.coalingot.item.entity.Item; + +public interface ItemRepository extends JpaRepository { +} diff --git a/src/main/java/se/project/coalingot/item/service/ItemService.java b/src/main/java/se/project/coalingot/item/service/ItemService.java new file mode 100644 index 0000000..5687219 --- /dev/null +++ b/src/main/java/se/project/coalingot/item/service/ItemService.java @@ -0,0 +1,13 @@ +package se.project.coalingot.item.service; + +import se.project.coalingot.item.entity.Item; +import se.project.coalingot.item.entity.ItemRequest; + +import java.util.List; + +public interface ItemService { + List getAllItem(); + Item postItem(ItemRequest itemRequest); + Item itemDetail(Long id); + Item endAuction(Long auctionId); +} diff --git a/src/main/java/se/project/coalingot/item/service/ItemServiceImpl.java b/src/main/java/se/project/coalingot/item/service/ItemServiceImpl.java new file mode 100644 index 0000000..b5bf8d7 --- /dev/null +++ b/src/main/java/se/project/coalingot/item/service/ItemServiceImpl.java @@ -0,0 +1,38 @@ +package se.project.coalingot.item.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import se.project.coalingot.item.dao.ItemDao; +import se.project.coalingot.item.entity.Item; +import se.project.coalingot.item.entity.ItemRequest; + +import java.util.List; + +@Service +public class ItemServiceImpl implements ItemService{ + @Autowired + ItemDao itemDao; + + @Autowired + + + @Override + public List getAllItem() { + return itemDao.getAllItem(); + } + + @Override + public Item postItem(ItemRequest itemRequest) { + return itemDao.postItem(itemRequest); + } + + @Override + public Item itemDetail(Long id) { + return itemDao.itemDetail(id); + } + + @Override + public Item endAuction(Long auctionId) { + return itemDao.endAuction(auctionId); + } +} diff --git a/src/main/java/se/project/coalingot/security/JwtTokenUtil.java b/src/main/java/se/project/coalingot/security/JwtTokenUtil.java new file mode 100644 index 0000000..d3c69f0 --- /dev/null +++ b/src/main/java/se/project/coalingot/security/JwtTokenUtil.java @@ -0,0 +1,166 @@ +package se.project.coalingot.security; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.mobile.device.Device; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; +import se.project.coalingot.security.entity.JwtUser; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@Component +public class JwtTokenUtil implements Serializable { + + static final String CLAIM_KEY_USERNAME = "sub"; + static final String CLAIM_KEY_AUDIENCE = "audience"; + static final String CLAIM_KEY_CREATED = "created"; + private static final long serialVersionUID = -3301605591108950415L; + private static final String AUDIENCE_UNKNOWN = "unknown"; + private static final String AUDIENCE_WEB = "web"; + private static final String AUDIENCE_MOBILE = "mobile"; + private static final String AUDIENCE_TABLET = "tablet"; + + @Value("${jwt.secret}") + private String secret; + + @Value("${jwt.expiration}") + private Long expiration; + + public String getUsernameFromToken(String token) { + String username; + try { + final Claims claims = getClaimsFromToken(token); + username = claims.getSubject(); + } catch (Exception e) { + username = null; + } + return username; + } + + public Date getCreatedDateFromToken(String token) { + Date created; + try { + final Claims claims = getClaimsFromToken(token); + created = new Date((Long) claims.get(CLAIM_KEY_CREATED)); + } catch (Exception e) { + created = null; + } + return created; + } + + public Date getExpirationDateFromToken(String token) { + Date expiration; + try { + final Claims claims = getClaimsFromToken(token); + expiration = claims.getExpiration(); + } catch (Exception e) { + expiration = null; + } + return expiration; + } + + public String getAudienceFromToken(String token) { + String audience; + try { + final Claims claims = getClaimsFromToken(token); + audience = (String) claims.get(CLAIM_KEY_AUDIENCE); + } catch (Exception e) { + audience = null; + } + return audience; + } + + private Claims getClaimsFromToken(String token) { + Claims claims; + try { + claims = Jwts.parser() + .setSigningKey(secret) + .parseClaimsJws(token) + .getBody(); + } catch (Exception e) { + claims = null; + } + return claims; + } + + private Date generateExpirationDate() { + return new Date(System.currentTimeMillis() + expiration * 1000); + } + + private Boolean isTokenExpired(String token) { + final Date expiration = getExpirationDateFromToken(token); + return expiration.before(new Date()); + } + + private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) { + return (lastPasswordReset != null && created.before(lastPasswordReset)); + } + + private String generateAudience(Device device) { + String audience = AUDIENCE_UNKNOWN; + if (device.isNormal()) { + audience = AUDIENCE_WEB; + } else if (device.isTablet()) { + audience = AUDIENCE_TABLET; + } else if (device.isMobile()) { + audience = AUDIENCE_MOBILE; + } + return audience; + } + + private Boolean ignoreTokenExpiration(String token) { + String audience = getAudienceFromToken(token); + return (AUDIENCE_TABLET.equals(audience) || AUDIENCE_MOBILE.equals(audience)); + } + + public String generateToken(UserDetails userDetails, Device device) { + Map claims = new HashMap<>(); + claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername()); + claims.put(CLAIM_KEY_AUDIENCE, generateAudience(device)); + claims.put(CLAIM_KEY_CREATED, new Date()); + return generateToken(claims); + } + + String generateToken(Map claims) { + return Jwts.builder() + .setClaims(claims) + .setExpiration(generateExpirationDate()) + .signWith(SignatureAlgorithm.HS512, secret) + .compact(); + } + + public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) { + final Date created = getCreatedDateFromToken(token); + return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset) + && (!isTokenExpired(token) || ignoreTokenExpiration(token)); + } + + public String refreshToken(String token) { + String refreshedToken; + try { + final Claims claims = getClaimsFromToken(token); + claims.put(CLAIM_KEY_CREATED, new Date()); + refreshedToken = generateToken(claims); + } catch (Exception e) { + refreshedToken = null; + } + return refreshedToken; + } + + public Boolean validateToken(String token, UserDetails userDetails) { + JwtUser user = (JwtUser) userDetails; + final String username = getUsernameFromToken(token); + final Date created = getCreatedDateFromToken(token); + //final Date expiration = getExpirationDateFromToken(token); + return ( + username.equals(user.getUsername()) + && !isTokenExpired(token) + && !isCreatedBeforeLastPasswordReset(created, user.getLastPasswordResetDate())); + } +} \ No newline at end of file diff --git a/src/main/java/se/project/coalingot/security/JwtUserFactory.java b/src/main/java/se/project/coalingot/security/JwtUserFactory.java new file mode 100644 index 0000000..8400b94 --- /dev/null +++ b/src/main/java/se/project/coalingot/security/JwtUserFactory.java @@ -0,0 +1,36 @@ +package se.project.coalingot.security; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import se.project.coalingot.security.entity.Authority; +import se.project.coalingot.security.entity.JwtUser; +import se.project.coalingot.security.entity.User; + +import java.util.List; +import java.util.stream.Collectors; + +public final class JwtUserFactory { + + private JwtUserFactory() { + } + + public static JwtUser create(User user) { + return new JwtUser( + user.getId(), + user.getUsername(), + user.getFirstname(), + user.getLastname(), + user.getEmail(), + user.getPassword(), + mapToGrantedAuthorities(user.getAuthorities()), + user.getEnabled(), + user.getLastPasswordResetDate() + ); + } + + private static List mapToGrantedAuthorities(List authorities) { + return authorities.stream() + .map(authority -> new SimpleGrantedAuthority(authority.getName().name())) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/se/project/coalingot/security/config/MobileConfig.java b/src/main/java/se/project/coalingot/security/config/MobileConfig.java new file mode 100644 index 0000000..e957906 --- /dev/null +++ b/src/main/java/se/project/coalingot/security/config/MobileConfig.java @@ -0,0 +1,46 @@ +package se.project.coalingot.security.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.mobile.device.DeviceHandlerMethodArgumentResolver; +import org.springframework.mobile.device.DeviceResolverHandlerInterceptor; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.List; + +@Configuration +public class MobileConfig implements WebMvcConfigurer { +// @Autowired +// DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor; +// +// +// @Autowired +// DeviceHandlerMethodArgumentResolver deviceHandlerMethodArgumentResolver; + + @Bean + public DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor(){ + return new DeviceResolverHandlerInterceptor(); + }; + + + @Bean + public DeviceHandlerMethodArgumentResolver deviceHandlerMethodArgumentResolver(){ + return new DeviceHandlerMethodArgumentResolver(); + }; + + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(deviceResolverHandlerInterceptor()); + } + + @Override + public void addArgumentResolvers( + List argumentResolvers) { + argumentResolvers.add(deviceHandlerMethodArgumentResolver()); + } + +} \ No newline at end of file diff --git a/src/main/java/se/project/coalingot/security/controller/AuthenticationRestController.java b/src/main/java/se/project/coalingot/security/controller/AuthenticationRestController.java new file mode 100644 index 0000000..4545f7a --- /dev/null +++ b/src/main/java/se/project/coalingot/security/controller/AuthenticationRestController.java @@ -0,0 +1,122 @@ +package se.project.coalingot.security.controller; + + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.mobile.device.Device; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.web.bind.annotation.*; +import se.project.coalingot.auctionuser.entity.AuctionUser; +import se.project.coalingot.auctionuser.repository.AuctionUserRepository; +import se.project.coalingot.security.JwtTokenUtil; +import se.project.coalingot.security.entity.Authority; +import se.project.coalingot.security.entity.AuthorityName; +import se.project.coalingot.security.entity.JwtUser; +import se.project.coalingot.security.entity.User; +import se.project.coalingot.security.repository.AuthorityRepository; +import se.project.coalingot.security.repository.UserRepository; +import se.project.coalingot.util.AuctionMapper; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.Map; + +@RestController +@CrossOrigin(maxAge = 3600) +public class AuthenticationRestController { + + @Value("${jwt.header}") + private String tokenHeader; + + @Autowired + private AuthenticationManager authenticationManager; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + UserRepository userRepository; + + @Autowired + AuctionUserRepository auctionUserRepository; + + @Autowired + AuthorityRepository authorityRepository; + + + + @PostMapping("${jwt.route.authentication.path}") + public ResponseEntity createAuthenticationToken(@RequestBody JwtAuthenticationRequest authenticationRequest, Device device) throws AuthenticationException { + + // Perform the security + final Authentication authentication = authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + authenticationRequest.getUsername(), + authenticationRequest.getPassword() + ) + ); + SecurityContextHolder.getContext().setAuthentication(authentication); + + // Reload password post-security so we can generate token + final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername()); + final String token = jwtTokenUtil.generateToken(userDetails, device); + Map result = new HashMap(); + result.put("token", token); + User user = userRepository.findById(((JwtUser) userDetails).getId()).orElse(null); + if (user != null) { + result.put("user", AuctionMapper.INSTANCE.getUserAuthDto(user)); + } + + return ResponseEntity.ok(result); + } + + + @GetMapping(value = "${jwt.route.authentication.refresh}") + public ResponseEntity refreshAndGetAuthenticationToken(HttpServletRequest request) { + String token = request.getHeader(tokenHeader); + String username = jwtTokenUtil.getUsernameFromToken(token); + JwtUser user = (JwtUser) userDetailsService.loadUserByUsername(username); + + if (jwtTokenUtil.canTokenBeRefreshed(token, user.getLastPasswordResetDate())) { + String refreshedToken = jwtTokenUtil.refreshToken(token); + return ResponseEntity.ok(new JwtAuthenticationResponse(refreshedToken) + "You are now currently logout"); + } else { + return ResponseEntity.badRequest().body(null); + } + } + + @PostMapping("${jwt.route.register.path}") + public ResponseEntity registerAuthentication(@RequestBody JwtAuthenticationRequest authenticationRequest, Device device) throws AuthenticationException { + Authority authUser = Authority.builder().name(AuthorityName.ROLE_USER).build(); + authorityRepository.save(authUser); + PasswordEncoder encoder = new BCryptPasswordEncoder(); + if (userRepository.findByUsername(authenticationRequest.getUsername()) == null ){ + AuctionUser newUser = new AuctionUser(); + newUser.setUsername(authenticationRequest.getUsername()); + newUser.setPassword(encoder.encode(authenticationRequest.getPassword())); + newUser.setFirstname(authenticationRequest.getFirstname()); + newUser.setLastname(authenticationRequest.getLastname()); + newUser.setEmail(authenticationRequest.getEmail()); + newUser.setEnabled(true); + auctionUserRepository.save(newUser); + return ResponseEntity.ok("Registration successful"); + }else { + return (ResponseEntity) ResponseEntity.status(HttpStatus.BAD_GATEWAY); + } + } + + +} diff --git a/src/main/java/se/project/coalingot/security/controller/JwtAuthenticationEntryPoint.java b/src/main/java/se/project/coalingot/security/controller/JwtAuthenticationEntryPoint.java new file mode 100644 index 0000000..d7e27c3 --- /dev/null +++ b/src/main/java/se/project/coalingot/security/controller/JwtAuthenticationEntryPoint.java @@ -0,0 +1,25 @@ +package se.project.coalingot.security.controller; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.Serializable; + +@Component +public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable { + + private static final long serialVersionUID = -8970718410437077606L; + + @Override + public void commence(HttpServletRequest request, + HttpServletResponse response, + AuthenticationException authException) throws IOException { + // This is invoked when user tries to access a secured REST resource without supplying any credentials + // We should just send a 401 Unauthorized response because there is no 'login page' to redirect to + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + } +} \ No newline at end of file diff --git a/src/main/java/se/project/coalingot/security/controller/JwtAuthenticationRequest.java b/src/main/java/se/project/coalingot/security/controller/JwtAuthenticationRequest.java new file mode 100644 index 0000000..3ac6062 --- /dev/null +++ b/src/main/java/se/project/coalingot/security/controller/JwtAuthenticationRequest.java @@ -0,0 +1,100 @@ +package se.project.coalingot.security.controller; + +import java.io.Serializable; +import java.util.Date; + +/** + * Created by stephan on 20.03.16. + */ +public class JwtAuthenticationRequest implements Serializable { + + private static final long serialVersionUID = -8445943548965154778L; + + private String username; + private String password; + private String email; + private String sex; + private String firstname; + private String lastname; + + public String getSex() { + return sex; + } + + public void setSex(String sex) { + this.sex = sex; + } + + public Date getDateOfBirth() { + return dateOfBirth; + } + + public void setDateOfBirth(Date dateOfBirth) { + this.dateOfBirth = dateOfBirth; + } + + private String hometown; + private Date dateOfBirth; + + public JwtAuthenticationRequest() { + super(); + } + + public JwtAuthenticationRequest(String username, String password, String email, String sex, String firstname, String lastname, String hometown, Date dateOfBirth) { + this.username = username; + this.password = password; + this.email = email; + this.sex = sex; + this.firstname = firstname; + this.lastname = lastname; + this.hometown = hometown; + this.dateOfBirth = dateOfBirth; + } + public String getUsername() { + return this.username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return this.password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getEmail() { + return this.email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getFirstname() { + return firstname; + } + + public void setFirstname(String firstname) { + this.firstname = firstname; + } + + public String getLastname() { + return lastname; + } + + public void setLastname(String lastname) { + this.lastname = lastname; + } + + public String getHometown() { + return hometown; + } + + public void setHometown(String hometown) { + this.hometown = hometown; + } +} diff --git a/src/main/java/se/project/coalingot/security/controller/JwtAuthenticationResponse.java b/src/main/java/se/project/coalingot/security/controller/JwtAuthenticationResponse.java new file mode 100644 index 0000000..6e3ea2f --- /dev/null +++ b/src/main/java/se/project/coalingot/security/controller/JwtAuthenticationResponse.java @@ -0,0 +1,21 @@ +package se.project.coalingot.security.controller; + +import java.io.Serializable; + +/** + * Created by stephan on 20.03.16. + */ +public class JwtAuthenticationResponse implements Serializable { + + private static final long serialVersionUID = 1250166508152483573L; + + private final String token; + + public JwtAuthenticationResponse(String token) { + this.token = token; + } + + public String getToken() { + return this.token; + } +} diff --git a/src/main/java/se/project/coalingot/security/controller/JwtAuthenticationTokenFilter.java b/src/main/java/se/project/coalingot/security/controller/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..1e21d51 --- /dev/null +++ b/src/main/java/se/project/coalingot/security/controller/JwtAuthenticationTokenFilter.java @@ -0,0 +1,62 @@ +package se.project.coalingot.security.controller; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.web.filter.OncePerRequestFilter; +import se.project.coalingot.security.JwtTokenUtil; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { + + private final Log logger = LogFactory.getLog(this.getClass()); + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + @Value("${jwt.header}") + private String tokenHeader; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { + String authToken = request.getHeader(this.tokenHeader); + + if (authToken != null && authToken.startsWith("Bearer ")) { + authToken = authToken.substring(7); + } + + String username = jwtTokenUtil.getUsernameFromToken(authToken); + + if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { + + // It is not compelling necessary to load the use details from the database. You could also store the information + // in the token and read it from it. It's up to you ;) + UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); + + // For simple validation it is completely sufficient to just check the token integrity. You don't have to call + // the database compellingly. Again it's up to you ;) + if (jwtTokenUtil.validateToken(authToken, userDetails)) { + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + logger.info("authenticated user " + username + ", setting security context"); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + + chain.doFilter(request, response); + } +} \ No newline at end of file diff --git a/src/main/java/se/project/coalingot/security/dto/UserAuthDto.java b/src/main/java/se/project/coalingot/security/dto/UserAuthDto.java new file mode 100644 index 0000000..d5d1690 --- /dev/null +++ b/src/main/java/se/project/coalingot/security/dto/UserAuthDto.java @@ -0,0 +1,18 @@ +package se.project.coalingot.security.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserAuthDto { + Long id; + String username; + List authorities; +} \ No newline at end of file diff --git a/src/main/java/se/project/coalingot/security/entity/Authority.java b/src/main/java/se/project/coalingot/security/entity/Authority.java new file mode 100644 index 0000000..b2340fa --- /dev/null +++ b/src/main/java/se/project/coalingot/security/entity/Authority.java @@ -0,0 +1,33 @@ +package se.project.coalingot.security.entity; + + +import com.fasterxml.jackson.annotation.JsonBackReference; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +import javax.persistence.*; + +import java.util.List; + +@Entity + +@Data +@Builder +@AllArgsConstructor +public class Authority { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "authority_seq") + @SequenceGenerator(name = "authority_seq", sequenceName = "authority_seq", allocationSize = 1) + private Long id; + @Enumerated(EnumType.STRING) + private AuthorityName name; + @ManyToMany(mappedBy = "authorities", fetch = FetchType.LAZY, cascade = CascadeType.ALL) + private List users; + + public Authority() { + + } + +} \ No newline at end of file diff --git a/src/main/java/se/project/coalingot/security/entity/AuthorityName.java b/src/main/java/se/project/coalingot/security/entity/AuthorityName.java new file mode 100644 index 0000000..d8a46e4 --- /dev/null +++ b/src/main/java/se/project/coalingot/security/entity/AuthorityName.java @@ -0,0 +1,5 @@ +package se.project.coalingot.security.entity; + +public enum AuthorityName { + ROLE_USER, ROLE_ADMIN +} \ No newline at end of file diff --git a/src/main/java/se/project/coalingot/security/entity/JwtUser.java b/src/main/java/se/project/coalingot/security/entity/JwtUser.java new file mode 100644 index 0000000..b3e2894 --- /dev/null +++ b/src/main/java/se/project/coalingot/security/entity/JwtUser.java @@ -0,0 +1,106 @@ +package se.project.coalingot.security.entity; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.Date; + +/** + * Created by stephan on 20.03.16. + */ +public class JwtUser implements UserDetails { + + private final Long id; + private final String username; + private final String firstname; + private final String lastname; + private final String password; + private final String email; + private final Collection authorities; + private final boolean enabled; + private final Date lastPasswordResetDate; + + public JwtUser( + Long id, + String username, + String firstname, + String lastname, + String email, + String password, Collection authorities, + boolean enabled, + Date lastPasswordResetDate + ) { + this.id = id; + this.username = username; + this.firstname = firstname; + this.lastname = lastname; + this.email = email; + this.password = password; + this.authorities = authorities; + this.enabled = enabled; + this.lastPasswordResetDate = lastPasswordResetDate; + } + + @JsonIgnore + public Long getId() { + return id; + } + + @Override + public String getUsername() { + return username; + } + + @JsonIgnore + @Override + public boolean isAccountNonExpired() { + return true; + } + + @JsonIgnore + @Override + public boolean isAccountNonLocked() { + return true; + } + + @JsonIgnore + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + public String getFirstname() { + return firstname; + } + + public String getLastname() { + return lastname; + } + + public String getEmail() { + return email; + } + + @JsonIgnore + @Override + public String getPassword() { + return password; + } + + @Override + public Collection getAuthorities() { + return authorities; + } + + @Override + public boolean isEnabled() { + return enabled; + } + + @JsonIgnore + public Date getLastPasswordResetDate() { + return lastPasswordResetDate; + } +} diff --git a/src/main/java/se/project/coalingot/security/entity/User.java b/src/main/java/se/project/coalingot/security/entity/User.java new file mode 100644 index 0000000..c7e42b8 --- /dev/null +++ b/src/main/java/se/project/coalingot/security/entity/User.java @@ -0,0 +1,63 @@ +package se.project.coalingot.security.entity; + + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.sun.istack.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.Cascade; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + + +@Entity +@Builder +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +@AllArgsConstructor +@NoArgsConstructor +public class User { + + @Id + @Column(name = "ID") + @GeneratedValue(strategy = GenerationType.AUTO) + protected Long id; + + @Column(name = "USERNAME", length = 50, unique = true) + @NotNull + protected String username; + + @Column(name = "PASSWORD", length = 100) + @NotNull + protected String password; + + @Column(name="EMAIL",length = 50) + @NotNull + protected String email; + + @Column(name = "FIRSTNAME", length = 50) + @NotNull + protected String firstname; + + @Column(name = "LASTNAME", length = 50) + @NotNull + protected String lastname; + + @Column(name = "ENABLED") + @NotNull + protected Boolean enabled; + + @Column(name = "LASTPASSWORDRESETDATE") + @Temporal(TemporalType.TIMESTAMP) + @NotNull + protected Date lastPasswordResetDate; + + @Builder.Default + @ManyToMany(fetch = FetchType.EAGER) + protected List authorities = new ArrayList<>(); +} \ No newline at end of file diff --git a/src/main/java/se/project/coalingot/security/repository/AuthorityRepository.java b/src/main/java/se/project/coalingot/security/repository/AuthorityRepository.java new file mode 100644 index 0000000..57c33c2 --- /dev/null +++ b/src/main/java/se/project/coalingot/security/repository/AuthorityRepository.java @@ -0,0 +1,10 @@ +package se.project.coalingot.security.repository; + + +import org.springframework.data.jpa.repository.JpaRepository; +import se.project.coalingot.security.entity.Authority; +import se.project.coalingot.security.entity.AuthorityName; + +public interface AuthorityRepository extends JpaRepository { + Authority findByName(AuthorityName input); +} diff --git a/src/main/java/se/project/coalingot/security/repository/UserRepository.java b/src/main/java/se/project/coalingot/security/repository/UserRepository.java new file mode 100644 index 0000000..fc18589 --- /dev/null +++ b/src/main/java/se/project/coalingot/security/repository/UserRepository.java @@ -0,0 +1,15 @@ +package se.project.coalingot.security.repository; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import se.project.coalingot.security.entity.Authority; +import se.project.coalingot.security.entity.User; + +import java.util.Collection; +import java.util.List; + +public interface UserRepository extends JpaRepository { + User findByUsername(String username); + List findAll(); +} diff --git a/src/main/java/se/project/coalingot/security/service/JwtAuthenticationResponse.java b/src/main/java/se/project/coalingot/security/service/JwtAuthenticationResponse.java new file mode 100644 index 0000000..8f0bacb --- /dev/null +++ b/src/main/java/se/project/coalingot/security/service/JwtAuthenticationResponse.java @@ -0,0 +1,22 @@ +package se.project.coalingot.security.service; + +import java.io.Serializable; + +/** + * Created by stephan on 20.03.16. + * Modified by Sahachan on 20.10.21 + */ +public class JwtAuthenticationResponse implements Serializable { + + private static final long serialVersionUID = 1250166508152483573L; + + private final String token; + + public JwtAuthenticationResponse(String token) { + this.token = token; + } + + public String getToken() { + return this.token; + } +} diff --git a/src/main/java/se/project/coalingot/security/service/JwtUserDetailsServiceImpl.java b/src/main/java/se/project/coalingot/security/service/JwtUserDetailsServiceImpl.java new file mode 100644 index 0000000..b3c1afb --- /dev/null +++ b/src/main/java/se/project/coalingot/security/service/JwtUserDetailsServiceImpl.java @@ -0,0 +1,32 @@ +package se.project.coalingot.security.service; + +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 se.project.coalingot.security.JwtUserFactory; +import se.project.coalingot.security.entity.User; +import se.project.coalingot.security.repository.UserRepository; + +/** + * Created by stephan on 20.03.16. + * Modified by Sahachan on 20.10.21 + */ +@Service +public class JwtUserDetailsServiceImpl implements UserDetailsService { + + @Autowired + private UserRepository userRepository; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + User user = userRepository.findByUsername(username); + + if (user == null) { + throw new UsernameNotFoundException(String.format("No user found with username '%s'.", username)); + } else { + return JwtUserFactory.create(user); + } + } +} diff --git a/src/main/java/se/project/coalingot/util/AuctionMapper.java b/src/main/java/se/project/coalingot/util/AuctionMapper.java new file mode 100644 index 0000000..e01d763 --- /dev/null +++ b/src/main/java/se/project/coalingot/util/AuctionMapper.java @@ -0,0 +1,50 @@ +package se.project.coalingot.util; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; +import se.project.coalingot.auction.dto.AuctionDto; +import se.project.coalingot.auction.dto.AuctionHistoryDto; +import se.project.coalingot.auction.entity.Auction; +import se.project.coalingot.auction.entity.AuctionHistory; +import se.project.coalingot.auctionuser.dto.AuctionUserDto; +import se.project.coalingot.auctionuser.dto.AuctionUserPaticipantDto; +import se.project.coalingot.auctionuser.entity.AuctionUser; +import se.project.coalingot.item.dto.ItemAuctionDto; +import se.project.coalingot.item.dto.ItemDto; +import se.project.coalingot.item.dto.ItemHistoryDto; +import se.project.coalingot.item.entity.Item; +import se.project.coalingot.security.dto.UserAuthDto; +import se.project.coalingot.security.entity.User; + +import java.util.List; +import java.util.stream.Collectors; + +@Mapper(imports = Collectors.class) +public interface AuctionMapper { + AuctionMapper INSTANCE = Mappers.getMapper(AuctionMapper.class); + + @Mapping(target = "authorities", expression = "java(user.getAuthorities().stream().map(auth -> auth.getName().name()).collect(Collectors.toList()))") + UserAuthDto getUserAuthDto(User user); + + ItemDto getItemDto(Item item); + List getItemDto(List items); + + ItemAuctionDto getItemAuctionDto(Item item); + List getItemAuctionDto(List items); + + ItemHistoryDto getItemHistoryDto(Item item); + List getItemHistoryDto(List items); + + AuctionDto seeAuction(Auction auction); + List seeAuction(List auctions); + + AuctionUserDto getAuctionUserDto(AuctionUser auctionUser); + List getAuctionUserDto(List auctionUser); + + AuctionUserPaticipantDto seePaticipant(AuctionUser auctionUser); + List seePaticipant(List actionUsers); + + AuctionHistory seeAuctionHistory(AuctionHistory auctionHistory); + List seeAuctionHistory(List auctionHistories); + +} diff --git a/src/main/resources/SE323.json b/src/main/resources/SE323.json new file mode 100644 index 0000000..2a5a398 --- /dev/null +++ b/src/main/resources/SE323.json @@ -0,0 +1,12 @@ +{ + "type": "service_account", + "project_id": "cmu-trp", + "private_key_id": "85dbae7a8c04163c3e5c188fdf62c179a4d787af", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDnfx/HX2HVK/9g\n/IjDgY2ed0ugA46Xs0TP9hZjlfpJa69rHJUQPDzJ5B77Oo+Q73ktG0WU+JX4u4p9\nGcU8vIxE0RGoVYPr7ttQkD9vObdlUiJGzjLTr9QnUn/0Xr6Wbpt3xGAUjwE9H6kI\nhUoC+krgo+P7nBDaIqVxgfQd905fCFrfYpPVd6xk40M+VZsuUSAzmYBAbLOTbdBl\nFGYLCQ7rl3HlWLKSTwrGuBNpWDDnchvisyoe5SPbnyLdm5FaODsxDFI//an865QA\nFG/lLEj6WVin1vDh5xS2SFQGNAz/hCnhdZH2acp4m2o4CN8i3JNQQ526pVGDSZCk\nzgNqYm93AgMBAAECggEAP4ST9aJoN5Nw6O2hoPMlJnvZFjijoWAg22bMUdrO5+JS\nKXOYOvIsQ8EB9zDkP4JVn1jCSNPEYpEiuJyfj8C0RBWRYLzGC7BoILzTivMtLPHS\nUdc1/vtZnMh4L1bnuGL06XHKYxmx31GWka3w1sxSSzzsyxbRUOj8uB5OGwLGUDB3\nFdaZH4ayGAgrlCldfISJjAy2qxQ6scrgbtZQzZ9CYIXIuNQo8XRBcnkW6WABJBit\n2wdyrikkJUe384TCDhsJGHbNJIcHF3AOQfGRYWouoPEsaeYq4Ror2hX9tr1ysFnD\nAu4s+NPjP8prci1Rl0qt4xA88/KIgWTql9KhD6wGsQKBgQD1hpB94u5kPFZqX5e3\nQ6WBLPfnowHuw1jn8ujS90RyC8khRnQVIS37WAa09mQeKM0XkGxehushcBP+oXxG\nyEoNqey7hQy93iCnAyg35wbATJ1foWMgsruejzHNpBAMYrxuH5ZO84DOKhyzoCUQ\nqrI4Cu0NZPWoUzhh7RRGmoXYCwKBgQDxX1hvjMbRN3dbCyVk9SXpVPTehNUIb4k+\nwF/psVYUuEiAwni7/7RWfYxOU6YM0iau6COxO7oVWTzEPCtI0iZWeqAQbtvqLXCd\nLau8uDHj+ayikO+3XcPVwtZK+nuQkwk675x3N2bkR7HVQAo/jh0+AR2A/DP/Hrw/\nekrEGMPtxQKBgEjqYKjyJwgfny5SG1VywokdWLYzA9TrsNCZpClbA7m25FF8gebw\nhp5ZYwyFC/Ck/1ubKYPdH6E7jsSVIrpGqy9pooOCHOmaOSpAVsZbVvbvCeGnpS/F\nxNBvCERhD98Nx5YQzWu/Byay/Pkfe0J63xijrgjHTeliZaE3bkkVhOBHAoGAPQMy\n4Y+eOghhPTxGCY0GNkLpWs4M44L+GEScef//mGE0wodl6W+rcClwK+RtFtSQPqoj\nS4ujb/4MpDXpYxDr6/Q3PbAoGru9uZ1vydZtlgjooHcugRVMiV4kuPM0BMmGDcW/\nsUrp0U5mH1d+v632qlOx14boxdZJE2qgN41jCVkCgYASFbJ/hutWMsuJ6aewagoK\n10nNjBk8M6zWr6uv7xDs2Y/iBcCaX8LiREY0xcPY1ew5vOKGBWftljPn+KAz1wDt\nP5HD8pCKYVdMDHi8dg4cUmFDiI3Fe0OMxQ96RxV275b44Ahgs2IaWvHtCaGvkWQt\n7ijZyPKvTPrBQihJMe3YFQ==\n-----END PRIVATE KEY-----\n", + "client_email": "cmu-trp@appspot.gserviceaccount.com", + "client_id": "111561331206365493126", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/cmu-trp%40appspot.gserviceaccount.com" +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 8b13789..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..16b1ead --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,26 @@ +spring: + profiles: + active: + - db + datasource: + url: jdbc:mysql://localhost:3306/auctioningot?createDatabaseIfNotExist=true&autoReconnect=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8 + driver-class-name: com.mysql.cj.jdbc.Driver + username: root + password: password + jpa: + hibernate: + ddl-auto: create + servlet: + multipart: + max-file-size: 10MB +jwt: + header: Authorization + secret: mySecret + expiration: 604800 + route: + authentication: + path: auth + refresh: refresh + register: + path: registers + refresh: refresh