From 7a2a366dd51cba4368530dfe9c2158da382cfc2c Mon Sep 17 00:00:00 2001 From: djmil Date: Sun, 3 Sep 2023 20:38:40 +0200 Subject: [PATCH] SpringBoot introduce GameProposalController --- .../cordacheckers/ApiUserDetailsService.java | 43 ------------------- .../cordaclient/CordaClient.java | 9 +++- .../cordacheckers/cordaclient/dao/Color.java | 6 +++ .../cordaclient/dao/GameProposal.java | 4 +- .../djmil/cordacheckers/game/PlayerColor.java | 6 --- .../gameproposal/CreateGameProposal.java | 9 ---- .../gameproposal/GameProposal.java | 12 ++++++ .../GameProposalController.java | 29 +++++++------ .../HoldingIdentityResolver.java | 23 +++++----- .../{ApiUserDetails.java => user/User.java} | 8 ++-- .../djmil/cordacheckers/user/UserService.java | 39 +++++++++++++++++ 11 files changed, 97 insertions(+), 91 deletions(-) delete mode 100644 backend/src/main/java/djmil/cordacheckers/ApiUserDetailsService.java create mode 100644 backend/src/main/java/djmil/cordacheckers/cordaclient/dao/Color.java delete mode 100644 backend/src/main/java/djmil/cordacheckers/game/PlayerColor.java delete mode 100644 backend/src/main/java/djmil/cordacheckers/gameproposal/CreateGameProposal.java create mode 100644 backend/src/main/java/djmil/cordacheckers/gameproposal/GameProposal.java rename backend/src/main/java/djmil/cordacheckers/{ => gameproposal}/GameProposalController.java (70%) rename backend/src/main/java/djmil/cordacheckers/{cordaclient => user}/HoldingIdentityResolver.java (65%) rename backend/src/main/java/djmil/cordacheckers/{ApiUserDetails.java => user/User.java} (70%) create mode 100644 backend/src/main/java/djmil/cordacheckers/user/UserService.java diff --git a/backend/src/main/java/djmil/cordacheckers/ApiUserDetailsService.java b/backend/src/main/java/djmil/cordacheckers/ApiUserDetailsService.java deleted file mode 100644 index a5af87a..0000000 --- a/backend/src/main/java/djmil/cordacheckers/ApiUserDetailsService.java +++ /dev/null @@ -1,43 +0,0 @@ -package djmil.cordacheckers; - -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; - -import djmil.cordacheckers.cordaclient.HoldingIdentityResolver; -import djmil.cordacheckers.cordaclient.dao.HoldingIdentity; - -@Service -public class ApiUserDetailsService implements UserDetailsService { - - private final PasswordEncoder encoder; - private final HoldingIdentityResolver holdingIdentityResolver; - - public ApiUserDetailsService( - PasswordEncoder encoder, - HoldingIdentityResolver holdingIdentityNameResolver) { - this.encoder = encoder; - this.holdingIdentityResolver = holdingIdentityNameResolver; - } - - @Override - public ApiUserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - HoldingIdentity holdingIdentity = holdingIdentityResolver.getByCommonName(username); - if (holdingIdentity == null) { - throw new UsernameNotFoundException("Can't find HoldingIdentity for the user '"+username+ "'"); - } - - System.out.println("Load user "+username); - - User.UserBuilder userBuilder = User.builder(); - UserDetails user = userBuilder - .username(username) - .password(encoder.encode("qaz123")) - .build(); - - return new ApiUserDetails(user, holdingIdentity); - } -} diff --git a/backend/src/main/java/djmil/cordacheckers/cordaclient/CordaClient.java b/backend/src/main/java/djmil/cordacheckers/cordaclient/CordaClient.java index 7edbc37..7b6e0e0 100644 --- a/backend/src/main/java/djmil/cordacheckers/cordaclient/CordaClient.java +++ b/backend/src/main/java/djmil/cordacheckers/cordaclient/CordaClient.java @@ -17,12 +17,12 @@ import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.databind.ObjectMapper; import djmil.cordacheckers.cordaclient.dao.HoldingIdentity; +import djmil.cordacheckers.cordaclient.dao.Color; import djmil.cordacheckers.cordaclient.dao.VirtualNode; import djmil.cordacheckers.cordaclient.dao.VirtualNodeList; import djmil.cordacheckers.cordaclient.dao.flow.RequestBody; import djmil.cordacheckers.cordaclient.dao.flow.ResponseBody; import djmil.cordacheckers.cordaclient.dao.flow.arguments.Empty; -import djmil.cordacheckers.game.PlayerColor; @Service public class CordaClient { @@ -73,7 +73,12 @@ public class CordaClient { return gameProposalsJsonString; } - public String sendGameProposal(HoldingIdentity sender, HoldingIdentity receiver, PlayerColor receiverColor, String message) { + public String sendGameProposal( + HoldingIdentity sender, + HoldingIdentity receiver, + Color receiverColor, + String message + ) { return ""; } diff --git a/backend/src/main/java/djmil/cordacheckers/cordaclient/dao/Color.java b/backend/src/main/java/djmil/cordacheckers/cordaclient/dao/Color.java new file mode 100644 index 0000000..9211dc9 --- /dev/null +++ b/backend/src/main/java/djmil/cordacheckers/cordaclient/dao/Color.java @@ -0,0 +1,6 @@ +package djmil.cordacheckers.cordaclient.dao; + +public enum Color { + WHITE, + BLACK +} diff --git a/backend/src/main/java/djmil/cordacheckers/cordaclient/dao/GameProposal.java b/backend/src/main/java/djmil/cordacheckers/cordaclient/dao/GameProposal.java index 87f6d58..0d354f5 100644 --- a/backend/src/main/java/djmil/cordacheckers/cordaclient/dao/GameProposal.java +++ b/backend/src/main/java/djmil/cordacheckers/cordaclient/dao/GameProposal.java @@ -6,8 +6,8 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public record GameProposal( String sender, String recipient, - String youPlayAs, - String additionalMessage, + Color recipientColor, + String message, String id) { } diff --git a/backend/src/main/java/djmil/cordacheckers/game/PlayerColor.java b/backend/src/main/java/djmil/cordacheckers/game/PlayerColor.java deleted file mode 100644 index 9be7be9..0000000 --- a/backend/src/main/java/djmil/cordacheckers/game/PlayerColor.java +++ /dev/null @@ -1,6 +0,0 @@ -package djmil.cordacheckers.game; - -public enum PlayerColor { - WHITE, - BLACK -} diff --git a/backend/src/main/java/djmil/cordacheckers/gameproposal/CreateGameProposal.java b/backend/src/main/java/djmil/cordacheckers/gameproposal/CreateGameProposal.java deleted file mode 100644 index f7a46df..0000000 --- a/backend/src/main/java/djmil/cordacheckers/gameproposal/CreateGameProposal.java +++ /dev/null @@ -1,9 +0,0 @@ -package djmil.cordacheckers.gameproposal; - -public record CreateGameProposal( - String opponentName, - String opponentColor, - String message) -{ - -} diff --git a/backend/src/main/java/djmil/cordacheckers/gameproposal/GameProposal.java b/backend/src/main/java/djmil/cordacheckers/gameproposal/GameProposal.java new file mode 100644 index 0000000..00aac21 --- /dev/null +++ b/backend/src/main/java/djmil/cordacheckers/gameproposal/GameProposal.java @@ -0,0 +1,12 @@ +package djmil.cordacheckers.gameproposal; + +import djmil.cordacheckers.cordaclient.dao.Color; + +public record GameProposal( + String sender, + String recipient, + Color recipientColor, + String message) +{ + +} diff --git a/backend/src/main/java/djmil/cordacheckers/GameProposalController.java b/backend/src/main/java/djmil/cordacheckers/gameproposal/GameProposalController.java similarity index 70% rename from backend/src/main/java/djmil/cordacheckers/GameProposalController.java rename to backend/src/main/java/djmil/cordacheckers/gameproposal/GameProposalController.java index 7f24f44..46d584d 100644 --- a/backend/src/main/java/djmil/cordacheckers/GameProposalController.java +++ b/backend/src/main/java/djmil/cordacheckers/gameproposal/GameProposalController.java @@ -1,4 +1,4 @@ -package djmil.cordacheckers; +package djmil.cordacheckers.gameproposal; import java.net.URI; import java.util.List; @@ -11,11 +11,10 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.util.UriComponentsBuilder; import djmil.cordacheckers.cordaclient.CordaClient; -import djmil.cordacheckers.cordaclient.HoldingIdentityResolver; import djmil.cordacheckers.cordaclient.dao.HoldingIdentity; -import djmil.cordacheckers.cordaclient.dao.VirtualNode; -import djmil.cordacheckers.game.PlayerColor; -import djmil.cordacheckers.gameproposal.CreateGameProposal; +import djmil.cordacheckers.cordaclient.dao.Color; +import djmil.cordacheckers.user.HoldingIdentityResolver; +import djmil.cordacheckers.user.User; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -23,7 +22,7 @@ import org.springframework.web.bind.annotation.RequestMapping; @RestController -@RequestMapping("/gameproposal") +@RequestMapping("gameproposal") public class GameProposalController { @Autowired @@ -34,9 +33,9 @@ public class GameProposalController { @GetMapping public ResponseEntity findAllUnconsumed( - @AuthenticationPrincipal ApiUserDetails user + @AuthenticationPrincipal User player ) { - String gpList = cordaClient.listGameProposals(user.getHoldingIdentity()); + String gpList = cordaClient.listGameProposals(player.getHoldingIdentity()); return ResponseEntity.ok(gpList); } @@ -48,15 +47,17 @@ public class GameProposalController { // } @PostMapping() - public ResponseEntity create( - @AuthenticationPrincipal ApiUserDetails player, - @RequestBody CreateGameProposal gpRequest, + public ResponseEntity createGameProposal( + @AuthenticationPrincipal User sender, + @RequestBody GameProposal gpRequest, UriComponentsBuilder ucb ) { - final HoldingIdentity gpSender = player.getHoldingIdentity(); + + //sender.get + final HoldingIdentity gpSender = sender.getHoldingIdentity(); // TODO: throw execption with custom type - final HoldingIdentity gpReceiver = holdingIdentityResolver.getByCommonName(gpRequest.opponentName()); - final PlayerColor gpReceiverColor = PlayerColor.valueOf(gpRequest.opponentColor()); + final HoldingIdentity gpReceiver = holdingIdentityResolver.getByUsername(gpRequest.recipient()); + final Color gpReceiverColor = gpRequest.recipientColor(); String newGameProposalUuid = cordaClient.sendGameProposal( gpSender, diff --git a/backend/src/main/java/djmil/cordacheckers/cordaclient/HoldingIdentityResolver.java b/backend/src/main/java/djmil/cordacheckers/user/HoldingIdentityResolver.java similarity index 65% rename from backend/src/main/java/djmil/cordacheckers/cordaclient/HoldingIdentityResolver.java rename to backend/src/main/java/djmil/cordacheckers/user/HoldingIdentityResolver.java index d16801a..48c2c3f 100644 --- a/backend/src/main/java/djmil/cordacheckers/cordaclient/HoldingIdentityResolver.java +++ b/backend/src/main/java/djmil/cordacheckers/user/HoldingIdentityResolver.java @@ -1,4 +1,4 @@ -package djmil.cordacheckers.cordaclient; +package djmil.cordacheckers.user; import java.util.HashMap; import java.util.List; @@ -9,6 +9,7 @@ import javax.naming.InvalidNameException; import org.springframework.stereotype.Service; +import djmil.cordacheckers.cordaclient.CordaClient; import djmil.cordacheckers.cordaclient.dao.HoldingIdentity; import djmil.cordacheckers.cordaclient.dao.VirtualNode; @@ -18,10 +19,10 @@ public class HoldingIdentityResolver { /* * NOTE: Proof-of-Concept impementation - * Ideally, we want to be able to update HoldingIdentity cache, had the - * corda cluster configuration changed (aka in case of a cache miss) + * Ideally, we want to be able to force update cache, had the corda + * cluster configuration changed (aka in case of a cache miss) */ - final Map cache; + final Map cache; // PlayerName to ShortHash HoldingIdentityResolver(CordaClient cordaClient) { this.cache = setCache(cordaClient); @@ -37,27 +38,29 @@ public class HoldingIdentityResolver { var identity = vNode.holdingIdentity(); if (identity.isPlayer()) { - map.put(identity.getName().toLowerCase(locale), identity); + map.put( + identity.getName().toLowerCase(locale), + identity + ); } } } catch (InvalidNameException e) { // TODO: logs - System.out.println("Unable to get ShorHash map for Corda virtual nodes: "+e.getExplanation()); - e.printStackTrace(); + System.out.println("Unable to get ShorHash list of Corda VirtualNodes: "+e.getMessage()); } return map; } /* - * @param apiUserName + * @param playerName * HoldingIdentity x500 name typically looks like * "CN=Bob, OU=Player, O=Checkers, L=Kviv, C=UA" * CN - is a common name, expected to be unique for CordaCheckers setup. * * @return HoldingIdentity */ - public HoldingIdentity getByCommonName(String apiUserName) { - return this.cache.get(apiUserName.toLowerCase(locale)); + public HoldingIdentity getByUsername(String userName) { + return this.cache.get(userName.toLowerCase(locale)); } } diff --git a/backend/src/main/java/djmil/cordacheckers/ApiUserDetails.java b/backend/src/main/java/djmil/cordacheckers/user/User.java similarity index 70% rename from backend/src/main/java/djmil/cordacheckers/ApiUserDetails.java rename to backend/src/main/java/djmil/cordacheckers/user/User.java index 8e701eb..9c26f95 100644 --- a/backend/src/main/java/djmil/cordacheckers/ApiUserDetails.java +++ b/backend/src/main/java/djmil/cordacheckers/user/User.java @@ -1,14 +1,13 @@ -package djmil.cordacheckers; +package djmil.cordacheckers.user; -import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import djmil.cordacheckers.cordaclient.dao.HoldingIdentity; -public class ApiUserDetails extends User { +public class User extends org.springframework.security.core.userdetails.User { private final HoldingIdentity holdingIdentity; - public ApiUserDetails(UserDetails user, HoldingIdentity holdingIdentity) { + public User(UserDetails user, HoldingIdentity holdingIdentity) { super(user.getUsername(), user.getPassword(), user.isEnabled(), user.isAccountNonExpired(), user.isCredentialsNonExpired(), user.isAccountNonLocked(), user.getAuthorities()); this.holdingIdentity = holdingIdentity; @@ -17,5 +16,4 @@ public class ApiUserDetails extends User { public HoldingIdentity getHoldingIdentity() { return this.holdingIdentity; } - } \ No newline at end of file diff --git a/backend/src/main/java/djmil/cordacheckers/user/UserService.java b/backend/src/main/java/djmil/cordacheckers/user/UserService.java new file mode 100644 index 0000000..1327d19 --- /dev/null +++ b/backend/src/main/java/djmil/cordacheckers/user/UserService.java @@ -0,0 +1,39 @@ +package djmil.cordacheckers.user; + +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +@Service +public class UserService implements UserDetailsService { + + private final PasswordEncoder encoder; + private final HoldingIdentityResolver holdingIdentityResolver; + + public UserService( + PasswordEncoder encoder, + HoldingIdentityResolver holdingIdentityResolver) { + this.encoder = encoder; + this.holdingIdentityResolver = holdingIdentityResolver; + } + + @Override + public User loadUserByUsername(String username) throws UsernameNotFoundException { + final var holdingIdentity = this.holdingIdentityResolver.getByUsername(username); + if (holdingIdentity == null) { + throw new UsernameNotFoundException("Can't find HoldingIdentity for the user '"+username+ "'"); + } + + System.out.println("Load user "+username); + + org.springframework.security.core.userdetails.User.UserBuilder userBuilder = org.springframework.security.core.userdetails.User.builder(); + UserDetails baseUser = userBuilder + .username(username) + .password(this.encoder.encode("qaz123")) + .build(); + + return new User(baseUser, holdingIdentity); + } +}