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
+
+
-
+
+
+ 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 extends GrantedAuthority> authorities;
+ private final boolean enabled;
+ private final Date lastPasswordResetDate;
+
+ public JwtUser(
+ Long id,
+ String username,
+ String firstname,
+ String lastname,
+ String email,
+ String password, Collection extends GrantedAuthority> 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 extends GrantedAuthority> 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