Browse Source

add snapshot endpoint and encrypt portfolio snapshots (#8)

Daniel Bohry 8 months ago
parent
commit
b62e00f40d
20 changed files with 266 additions and 243 deletions
  1. 32 0
      src/main/java/com/danielbohry/stocks/api/portfolio/SnapshotController.java
  2. 0 18
      src/main/java/com/danielbohry/stocks/domain/Login.java
  3. 1 1
      src/main/java/com/danielbohry/stocks/domain/Portfolio.java
  4. 0 19
      src/main/java/com/danielbohry/stocks/domain/Snapshot.java
  5. 4 0
      src/main/java/com/danielbohry/stocks/domain/Stock.java
  6. 0 22
      src/main/java/com/danielbohry/stocks/domain/User.java
  7. 34 0
      src/main/java/com/danielbohry/stocks/domain/snapshot/PortfolioSnapshot.java
  8. 0 9
      src/main/java/com/danielbohry/stocks/repository/SnapshotRepository.java
  9. 0 10
      src/main/java/com/danielbohry/stocks/repository/UserRepository.java
  10. 1 1
      src/main/java/com/danielbohry/stocks/repository/portfolio/PortfolioEntity.java
  11. 1 1
      src/main/java/com/danielbohry/stocks/repository/portfolio/PortfolioRepository.java
  12. 18 0
      src/main/java/com/danielbohry/stocks/repository/snapshot/PortfolioSnapshotEntity.java
  13. 13 0
      src/main/java/com/danielbohry/stocks/repository/snapshot/SnapshotRepository.java
  14. 75 0
      src/main/java/com/danielbohry/stocks/service/EncryptService.java
  15. 7 68
      src/main/java/com/danielbohry/stocks/service/PortfolioEncryptService.java
  16. 7 13
      src/main/java/com/danielbohry/stocks/service/PortfolioService.java
  17. 29 4
      src/main/java/com/danielbohry/stocks/service/SnapshotService.java
  18. 38 0
      src/main/java/com/danielbohry/stocks/service/StockEncryptService.java
  19. 0 58
      src/main/java/com/danielbohry/stocks/service/UserService.java
  20. 6 19
      src/test/java/service/PortfolioServiceTest.java

+ 32 - 0
src/main/java/com/danielbohry/stocks/api/portfolio/SnapshotController.java

@@ -0,0 +1,32 @@
+package com.danielbohry.stocks.api.portfolio;
+
+import com.danielbohry.stocks.domain.snapshot.PortfolioSnapshot;
+import com.danielbohry.stocks.service.SnapshotService;
+import lombok.AllArgsConstructor;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("api/portfolios/{portfolioId}")
+@AllArgsConstructor
+@CrossOrigin
+public class SnapshotController {
+
+    private final SnapshotService service;
+
+    @GetMapping("snapshots")
+    public ResponseEntity<?> getSnapshots(@PathVariable String portfolioId) {
+        List<PortfolioSnapshot> response = service.getSnapshots(portfolioId);
+        return ResponseEntity.ok(response);
+    }
+
+    @PostMapping("snapshots")
+    public ResponseEntity<Void> createSnapshot(@PathVariable String portfolioId) {
+        service.createSnapshot(portfolioId);
+        return ResponseEntity.status(HttpStatus.CREATED).build();
+    }
+
+}

+ 0 - 18
src/main/java/com/danielbohry/stocks/domain/Login.java

@@ -1,18 +0,0 @@
-package com.danielbohry.stocks.domain;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.Instant;
-
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class Login {
-
-    private String username;
-    private String token;
-    private Instant expiresAt;
-
-}

+ 1 - 1
src/main/java/com/danielbohry/stocks/domain/Portfolio.java

@@ -1,6 +1,6 @@
 package com.danielbohry.stocks.domain;
 
-import com.danielbohry.stocks.repository.PortfolioEntity;
+import com.danielbohry.stocks.repository.portfolio.PortfolioEntity;
 import lombok.Builder;
 import lombok.Data;
 

+ 0 - 19
src/main/java/com/danielbohry/stocks/domain/Snapshot.java

@@ -1,19 +0,0 @@
-package com.danielbohry.stocks.domain;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.springframework.data.mongodb.core.mapping.Document;
-
-import java.time.Instant;
-
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-@Document("snapshots")
-public class Snapshot {
-
-    private Portfolio portfolio;
-    private Instant createdAt;
-
-}

+ 4 - 0
src/main/java/com/danielbohry/stocks/domain/Stock.java

@@ -1,12 +1,16 @@
 package com.danielbohry.stocks.domain;
 
+import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.math.BigDecimal;
 
 @Data
 @Builder
+@AllArgsConstructor
+@NoArgsConstructor
 public class Stock {
 
     private String code;

+ 0 - 22
src/main/java/com/danielbohry/stocks/domain/User.java

@@ -1,22 +0,0 @@
-package com.danielbohry.stocks.domain;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.springframework.data.annotation.Id;
-
-import java.time.Instant;
-import java.util.List;
-
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class User {
-
-    @Id
-    private String username;
-    private List<String> portfolios;
-    private Instant createdAt = Instant.now();
-    private Instant updatedAt = Instant.now();
-
-}

+ 34 - 0
src/main/java/com/danielbohry/stocks/domain/snapshot/PortfolioSnapshot.java

@@ -0,0 +1,34 @@
+package com.danielbohry.stocks.domain.snapshot;
+
+import com.danielbohry.stocks.domain.Stock;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.time.Instant;
+import java.util.List;
+
+@Data
+@Builder
+@AllArgsConstructor
+public class PortfolioSnapshot {
+
+    private String portfolioId;
+    private BigDecimal totalValue;
+    private Integer totalAssets;
+    private List<Stock> stocks;
+    private Instant createdAt;
+
+    public BigDecimal getTotalValue() {
+        return stocks.stream()
+            .map(Stock::getTotal)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+    }
+
+    public Integer getTotalAssets() {
+        return stocks.size();
+    }
+
+}

+ 0 - 9
src/main/java/com/danielbohry/stocks/repository/SnapshotRepository.java

@@ -1,9 +0,0 @@
-package com.danielbohry.stocks.repository;
-
-import com.danielbohry.stocks.domain.Snapshot;
-import org.springframework.data.mongodb.repository.MongoRepository;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface SnapshotRepository extends MongoRepository<Snapshot, String> {
-}

+ 0 - 10
src/main/java/com/danielbohry/stocks/repository/UserRepository.java

@@ -1,10 +0,0 @@
-package com.danielbohry.stocks.repository;
-
-import com.danielbohry.stocks.domain.User;
-import org.springframework.data.mongodb.repository.MongoRepository;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface UserRepository extends MongoRepository<User, String> {
-
-}

+ 1 - 1
src/main/java/com/danielbohry/stocks/repository/PortfolioEntity.java → src/main/java/com/danielbohry/stocks/repository/portfolio/PortfolioEntity.java

@@ -1,4 +1,4 @@
-package com.danielbohry.stocks.repository;
+package com.danielbohry.stocks.repository.portfolio;
 
 import lombok.AllArgsConstructor;
 import lombok.Builder;

+ 1 - 1
src/main/java/com/danielbohry/stocks/repository/PortfolioRepository.java → src/main/java/com/danielbohry/stocks/repository/portfolio/PortfolioRepository.java

@@ -1,4 +1,4 @@
-package com.danielbohry.stocks.repository;
+package com.danielbohry.stocks.repository.portfolio;
 
 import org.springframework.data.mongodb.repository.Aggregation;
 import org.springframework.data.mongodb.repository.MongoRepository;

+ 18 - 0
src/main/java/com/danielbohry/stocks/repository/snapshot/PortfolioSnapshotEntity.java

@@ -0,0 +1,18 @@
+package com.danielbohry.stocks.repository.snapshot;
+
+import lombok.Builder;
+import lombok.Data;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import java.time.Instant;
+
+@Data
+@Builder
+@Document("snapshot")
+public class PortfolioSnapshotEntity {
+
+    private String portfolioId;
+    private String encryptedStocks;
+    private Instant createdAt;
+
+}

+ 13 - 0
src/main/java/com/danielbohry/stocks/repository/snapshot/SnapshotRepository.java

@@ -0,0 +1,13 @@
+package com.danielbohry.stocks.repository.snapshot;
+
+import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface SnapshotRepository extends MongoRepository<PortfolioSnapshotEntity, String> {
+
+    List<PortfolioSnapshotEntity> findAllByPortfolioId(String portfolioId);
+
+}

+ 75 - 0
src/main/java/com/danielbohry/stocks/service/EncryptService.java

@@ -0,0 +1,75 @@
+package com.danielbohry.stocks.service;
+
+import com.danielbohry.stocks.repository.portfolio.PortfolioEntity;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
+import java.util.Base64;
+
+@Service
+public class EncryptService {
+
+    @Value("${encryption.key}")
+    private String secret;
+
+    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
+    private static final int IV_LENGTH = 16;
+    private static final int AES_KEY_SIZE = 16;
+
+    public String encrypt(String data) throws Exception {
+        SecretKeySpec key = getSecretKey();
+
+        byte[] iv = new byte[IV_LENGTH];
+        new SecureRandom().nextBytes(iv);
+        IvParameterSpec ivSpec = new IvParameterSpec(iv);
+
+        Cipher cipher = Cipher.getInstance(ALGORITHM);
+        cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
+
+        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
+        byte[] combined = new byte[IV_LENGTH + encrypted.length];
+        System.arraycopy(iv, 0, combined, 0, IV_LENGTH);
+        System.arraycopy(encrypted, 0, combined, IV_LENGTH, encrypted.length);
+
+        return Base64.getEncoder().encodeToString(combined);
+    }
+
+    public String decrypt(String encryptedData) throws Exception {
+        SecretKeySpec key = getSecretKey();
+
+        byte[] combined = Base64.getDecoder().decode(encryptedData);
+        byte[] iv = new byte[IV_LENGTH];
+        byte[] encrypted = new byte[combined.length - IV_LENGTH];
+
+        System.arraycopy(combined, 0, iv, 0, IV_LENGTH);
+        System.arraycopy(combined, IV_LENGTH, encrypted, 0, encrypted.length);
+
+        Cipher cipher = Cipher.getInstance(ALGORITHM);
+        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
+
+        byte[] decrypted = cipher.doFinal(encrypted);
+        return new String(decrypted, StandardCharsets.UTF_8);
+    }
+
+    public boolean isEncrypted(PortfolioEntity entity) {
+        return entity != null &&
+            entity.getEncryptedStocks() != null &&
+            !entity.getEncryptedStocks().isEmpty() &&
+            (entity.getStocks() == null || entity.getStocks().isEmpty());
+    }
+
+    private SecretKeySpec getSecretKey() {
+        byte[] keyBytes = new byte[AES_KEY_SIZE];
+        byte[] secretBytes = secret.getBytes(StandardCharsets.UTF_8);
+
+        int length = Math.min(secretBytes.length, AES_KEY_SIZE);
+        System.arraycopy(secretBytes, 0, keyBytes, 0, length);
+
+        return new SecretKeySpec(keyBytes, "AES");
+    }
+}

+ 7 - 68
src/main/java/com/danielbohry/stocks/service/PortfolioEncryptService.java

@@ -1,35 +1,25 @@
 package com.danielbohry.stocks.service;
 
-import com.danielbohry.stocks.repository.PortfolioEntity;
-import com.danielbohry.stocks.repository.PortfolioEntity.PortfolioStock;
+import com.danielbohry.stocks.repository.portfolio.PortfolioEntity.PortfolioStock;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import org.springframework.beans.factory.annotation.Value;
+import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 
-import javax.crypto.Cipher;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-import java.nio.charset.StandardCharsets;
-import java.security.SecureRandom;
-import java.util.Base64;
 import java.util.List;
 
 @Service
+@AllArgsConstructor
 public class PortfolioEncryptService {
 
-    @Value("${encryption.key}")
-    private String secret;
+    private final EncryptService service;
 
-    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
-    private static final int IV_LENGTH = 16;
-    private static final int AES_KEY_SIZE = 16;
     private static final ObjectMapper MAPPER = new ObjectMapper();
 
     public String encryptStocks(List<PortfolioStock> stocks) {
         try {
             String toEncrypt = MAPPER.writeValueAsString(stocks);
-            return encrypt(toEncrypt);
+            return service.encrypt(toEncrypt);
         } catch (Exception e) {
             throw new RuntimeException("Failed to encrypt stocks", e);
         }
@@ -37,7 +27,7 @@ public class PortfolioEncryptService {
 
     public List<PortfolioStock> decryptStocks(String encrypted) {
         try {
-            String data = decrypt(encrypted);
+            String data = service.decrypt(encrypted);
             return MAPPER.readValue(data, new TypeReference<>() {
             });
         } catch (Exception e) {
@@ -45,55 +35,4 @@ public class PortfolioEncryptService {
         }
     }
 
-    public String encrypt(String data) throws Exception {
-        SecretKeySpec key = getSecretKey();
-
-        byte[] iv = new byte[IV_LENGTH];
-        new SecureRandom().nextBytes(iv);
-        IvParameterSpec ivSpec = new IvParameterSpec(iv);
-
-        Cipher cipher = Cipher.getInstance(ALGORITHM);
-        cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
-
-        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
-        byte[] combined = new byte[IV_LENGTH + encrypted.length];
-        System.arraycopy(iv, 0, combined, 0, IV_LENGTH);
-        System.arraycopy(encrypted, 0, combined, IV_LENGTH, encrypted.length);
-
-        return Base64.getEncoder().encodeToString(combined);
-    }
-
-    public String decrypt(String encryptedData) throws Exception {
-        SecretKeySpec key = getSecretKey();
-
-        byte[] combined = Base64.getDecoder().decode(encryptedData);
-        byte[] iv = new byte[IV_LENGTH];
-        byte[] encrypted = new byte[combined.length - IV_LENGTH];
-
-        System.arraycopy(combined, 0, iv, 0, IV_LENGTH);
-        System.arraycopy(combined, IV_LENGTH, encrypted, 0, encrypted.length);
-
-        Cipher cipher = Cipher.getInstance(ALGORITHM);
-        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
-
-        byte[] decrypted = cipher.doFinal(encrypted);
-        return new String(decrypted, StandardCharsets.UTF_8);
-    }
-
-    public boolean isEncrypted(PortfolioEntity entity) {
-        return entity != null &&
-            entity.getEncryptedStocks() != null &&
-            !entity.getEncryptedStocks().isEmpty() &&
-            (entity.getStocks() == null || entity.getStocks().isEmpty());
-    }
-
-    private SecretKeySpec getSecretKey() {
-        byte[] keyBytes = new byte[AES_KEY_SIZE];
-        byte[] secretBytes = secret.getBytes(StandardCharsets.UTF_8);
-
-        int length = Math.min(secretBytes.length, AES_KEY_SIZE);
-        System.arraycopy(secretBytes, 0, keyBytes, 0, length);
-
-        return new SecretKeySpec(keyBytes, "AES");
-    }
-}
+}

+ 7 - 13
src/main/java/com/danielbohry/stocks/service/PortfolioService.java

@@ -7,9 +7,9 @@ import com.danielbohry.stocks.domain.Stock;
 import com.danielbohry.stocks.exception.BadRequestException;
 import com.danielbohry.stocks.exception.NotFoundException;
 import com.danielbohry.stocks.exception.UnauthorizedException;
-import com.danielbohry.stocks.repository.PortfolioEntity;
-import com.danielbohry.stocks.repository.PortfolioEntity.PortfolioStock;
-import com.danielbohry.stocks.repository.PortfolioRepository;
+import com.danielbohry.stocks.repository.portfolio.PortfolioEntity;
+import com.danielbohry.stocks.repository.portfolio.PortfolioEntity.PortfolioStock;
+import com.danielbohry.stocks.repository.portfolio.PortfolioRepository;
 import com.danielbohry.stocks.service.ExchangeService.ExchangeRateResponse;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -35,13 +35,7 @@ public class PortfolioService {
     private final PortfolioRepository repository;
     private final StockService stockService;
     private final ExchangeService exchangeService;
-    private final PortfolioEncryptService portfolioEncryptService;
-
-    public List<Portfolio> getAll() {
-        return repository.findAll().stream()
-            .map(Portfolio::convert)
-            .toList();
-    }
+    private final PortfolioEncryptService encryptService;
 
     public List<String> getAllIds() {
         return repository.findAllPortfolioIds();
@@ -59,7 +53,7 @@ public class PortfolioService {
 
         String encrypted = entity.getEncryptedStocks();
         if (encrypted != null) {
-            entity.setStocks(portfolioEncryptService.decryptStocks(encrypted));
+            entity.setStocks(encryptService.decryptStocks(encrypted));
         }
 
         Portfolio portfolio = convert(entity);
@@ -113,14 +107,14 @@ public class PortfolioService {
         validate(stocks);
 
         toUpdate.setUpdatedAt(now());
-        toUpdate.setEncryptedStocks(portfolioEncryptService.encryptStocks(stocks.stream()
+        toUpdate.setEncryptedStocks(encryptService.encryptStocks(stocks.stream()
             .map(stock -> new PortfolioStock(stock.getCode(), stock.getQuantity()))
             .toList()));
         toUpdate.setStocks(null);
 
         PortfolioEntity updated = repository.save(toUpdate);
 
-        List<PortfolioStock> decryptStocks = portfolioEncryptService.decryptStocks(updated.getEncryptedStocks());
+        List<PortfolioStock> decryptStocks = encryptService.decryptStocks(updated.getEncryptedStocks());
         updated.setStocks(decryptStocks);
 
         return convert(updated);

+ 29 - 4
src/main/java/com/danielbohry/stocks/service/SnapshotService.java

@@ -1,8 +1,9 @@
 package com.danielbohry.stocks.service;
 
 import com.danielbohry.stocks.domain.Portfolio;
-import com.danielbohry.stocks.domain.Snapshot;
-import com.danielbohry.stocks.repository.SnapshotRepository;
+import com.danielbohry.stocks.domain.snapshot.PortfolioSnapshot;
+import com.danielbohry.stocks.repository.snapshot.PortfolioSnapshotEntity;
+import com.danielbohry.stocks.repository.snapshot.SnapshotRepository;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.Scheduled;
@@ -19,6 +20,7 @@ public class SnapshotService {
 
     private final PortfolioService service;
     private final SnapshotRepository repository;
+    private final StockEncryptService encryptService;
 
     public static final String ONCE_PER_MONTH = "0 0 0 1 * *";
     public static final String DEFAULT_CURRENCY = "USD";
@@ -32,12 +34,35 @@ public class SnapshotService {
         saveSnapshots(portfolios);
     }
 
+    public List<PortfolioSnapshot> getSnapshots(String portfolioId) {
+        return repository.findAllByPortfolioId(portfolioId).stream()
+            .map(entity -> PortfolioSnapshot.builder()
+                .portfolioId(entity.getPortfolioId())
+                .stocks(encryptService.decryptStocks(entity.getEncryptedStocks()))
+                .createdAt(entity.getCreatedAt())
+                .build()
+            ).toList();
+    }
+
+    public void createSnapshot(String portfolioId) {
+        Portfolio portfolio = service.get(portfolioId, DEFAULT_CURRENCY);
+        saveSnapshots(List.of(portfolio));
+    }
+
     public void saveSnapshots(List<Portfolio> portfolios) {
         if (portfolios.isEmpty()) return;
 
-        List<Snapshot> snapshots = portfolios.stream()
+        List<PortfolioSnapshotEntity> snapshots = portfolios.stream()
             .filter(portfolio -> !portfolio.getStocks().isEmpty())
-            .map(portfolio -> new Snapshot(portfolio, now()))
+            .map(portfolio -> new PortfolioSnapshot(portfolio.getId(), portfolio.getTotalValue(), portfolio.getTotalAssets(), portfolio.getStocks(), now()))
+            .map(portfolio -> {
+                String encryptedStocks = encryptService.encryptStocks(portfolio.getStocks());
+                return PortfolioSnapshotEntity.builder()
+                    .portfolioId(portfolio.getPortfolioId())
+                    .encryptedStocks(encryptedStocks)
+                    .createdAt(now())
+                    .build();
+            })
             .toList();
 
         repository.saveAll(snapshots);

+ 38 - 0
src/main/java/com/danielbohry/stocks/service/StockEncryptService.java

@@ -0,0 +1,38 @@
+package com.danielbohry.stocks.service;
+
+import com.danielbohry.stocks.domain.Stock;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+@AllArgsConstructor
+public class StockEncryptService {
+
+    private final EncryptService service;
+
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
+    public String encryptStocks(List<Stock> stocks) {
+        try {
+            String toEncrypt = MAPPER.writeValueAsString(stocks);
+            return service.encrypt(toEncrypt);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to encrypt stocks", e);
+        }
+    }
+
+    public List<Stock> decryptStocks(String encrypted) {
+        try {
+            String data = service.decrypt(encrypted);
+            return MAPPER.readValue(data, new TypeReference<>() {
+            });
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to decrypt stocks", e);
+        }
+    }
+
+}

+ 0 - 58
src/main/java/com/danielbohry/stocks/service/UserService.java

@@ -1,58 +0,0 @@
-package com.danielbohry.stocks.service;
-
-import com.danielbohry.stocks.client.AuthClient;
-import com.danielbohry.stocks.domain.Login;
-import com.danielbohry.stocks.domain.User;
-import com.danielbohry.stocks.exception.BadRequestException;
-import com.danielbohry.stocks.exception.NotFoundException;
-import com.danielbohry.stocks.exception.UnauthorizedException;
-import com.danielbohry.stocks.repository.UserRepository;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.time.Instant;
-
-import static java.util.Collections.emptyList;
-
-@Service
-@AllArgsConstructor
-public class UserService {
-
-    private final AuthClient authClient;
-    private final UserRepository repository;
-
-    public Login register(String username, String password) {
-        if (repository.findById(username).isPresent()) {
-            throw new BadRequestException("Username already exists");
-        }
-
-        if (username.length() > 30) {
-            throw new BadRequestException("Username too long");
-        }
-
-        try {
-            AuthClient.AuthenticatedUser auth = authClient.register(username, password);
-            User user = repository.save(new User(username, emptyList(), Instant.now(), Instant.now()));
-
-            return new Login(user.getUsername(), auth.getToken(), auth.getExpirationDate());
-        } catch (Exception e) {
-            throw new UnauthorizedException(e.getMessage());
-        }
-
-    }
-
-    public Login login(String username, String password) {
-        User user = repository.findById(username)
-            .orElseThrow(() -> new NotFoundException("User not found"));
-
-        try {
-            AuthClient.AuthenticatedUser auth = authClient.authenticate(username, password);
-
-            return new Login(user.getUsername(), auth.getToken(), auth.getExpirationDate());
-        } catch (Exception e) {
-            throw new UnauthorizedException(e.getMessage());
-        }
-
-    }
-
-}

+ 6 - 19
src/test/java/service/PortfolioServiceTest.java

@@ -3,7 +3,7 @@ package service;
 import com.danielbohry.stocks.App;
 import com.danielbohry.stocks.domain.Portfolio;
 import com.danielbohry.stocks.domain.Stock;
-import com.danielbohry.stocks.repository.PortfolioRepository;
+import com.danielbohry.stocks.repository.portfolio.PortfolioRepository;
 import com.danielbohry.stocks.repository.StockRepository;
 import com.danielbohry.stocks.service.ExchangeService;
 import com.danielbohry.stocks.service.PortfolioEncryptService;
@@ -40,14 +40,14 @@ public class PortfolioServiceTest {
     private ExchangeService exchangeService;
 
     @Mock
-    private PortfolioEncryptService portfolioEncryptService;
+    private PortfolioEncryptService encryptService;
 
     private PortfolioService portfolioService;
 
     @BeforeEach
     public void setup() {
         StockService stockService = new StockService(stockRepository);
-        portfolioService = new PortfolioService(portfolioRepository, stockService, exchangeService, portfolioEncryptService);
+        portfolioService = new PortfolioService(portfolioRepository, stockService, exchangeService, encryptService);
     }
 
     @AfterEach
@@ -76,19 +76,6 @@ public class PortfolioServiceTest {
         assertNotNull(result.getId());
     }
 
-    @Test
-    public void shouldGetAllPortfolios() {
-        //given
-        Portfolio portfolio = portfolioService.create();
-        Portfolio portfolio2 = portfolioService.create();
-
-        //when
-        List<Portfolio> result = portfolioService.getAll();
-
-        //then
-        assertEquals(2, result.size());
-    }
-
     @Test
     public void shouldUpdateAPortfolio() {
         //given
@@ -96,9 +83,9 @@ public class PortfolioServiceTest {
 
         Portfolio portfolio = portfolioService.create();
         Stock newStock = Stock.builder()
-                .code("code")
-                .quantity(3)
-                .build();
+            .code("code")
+            .quantity(3)
+            .build();
 
         //when
         Portfolio result = portfolioService.update(portfolio.getId(), List.of(newStock));