From 3d9dbd2683c68614ce406435452c73554c96be0e Mon Sep 17 00:00:00 2001 From: djmil Date: Sun, 29 Oct 2023 21:45:48 +0100 Subject: [PATCH] GameCreate request - use HTTP POST request - diable CSRF on server --- .../djmil/cordacheckers/SecurityConfig.java | 20 ++++++++++ .../api/GameProposalController.java | 38 +++++++++---------- .../src/components/Game/GameAction/Create.jsx | 35 +++++++++++++---- 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/backend/src/main/java/djmil/cordacheckers/SecurityConfig.java b/backend/src/main/java/djmil/cordacheckers/SecurityConfig.java index 0112f40..628dae3 100644 --- a/backend/src/main/java/djmil/cordacheckers/SecurityConfig.java +++ b/backend/src/main/java/djmil/cordacheckers/SecurityConfig.java @@ -2,9 +2,11 @@ package djmil.cordacheckers; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.crypto.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity @@ -15,4 +17,22 @@ public class SecurityConfig { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } + @Bean + SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests() + .anyRequest() + .authenticated() + .and() + .formLogin() + .and() + .httpBasic(); + + http.csrf().disable(); + // GiteaIssue #2: Enable CSRF + // .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); + + return http.build(); + } + } diff --git a/backend/src/main/java/djmil/cordacheckers/api/GameProposalController.java b/backend/src/main/java/djmil/cordacheckers/api/GameProposalController.java index 65a12a4..66c83b5 100644 --- a/backend/src/main/java/djmil/cordacheckers/api/GameProposalController.java +++ b/backend/src/main/java/djmil/cordacheckers/api/GameProposalController.java @@ -1,12 +1,10 @@ package djmil.cordacheckers.api; import java.net.URI; -import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -24,7 +22,6 @@ import djmil.cordacheckers.cordaclient.dao.flow.arguments.ReqGameProposalCreate; import djmil.cordacheckers.user.HoldingIdentityResolver; import djmil.cordacheckers.user.User; - @RestController @RequestMapping("api/gameproposal") public class GameProposalController { @@ -34,34 +31,33 @@ public class GameProposalController { @Autowired HoldingIdentityResolver holdingIdentityResolver; - + @PostMapping() - public ResponseEntity createGameProposal( - @AuthenticationPrincipal User sender, - @RequestBody ReqGameProposalCreate gpRequest, - UriComponentsBuilder ucb - ) throws JsonMappingException, JsonProcessingException { + public ResponseEntity createGameProposal( + @AuthenticationPrincipal User sender, + @RequestBody ReqGameProposalCreate gpRequest, + UriComponentsBuilder ucb) throws JsonMappingException, JsonProcessingException { + final HoldingIdentity gpSender = sender.getHoldingIdentity(); - // TODO: throw execption with custom type final HoldingIdentity gpReceiver = holdingIdentityResolver.getByUsername(gpRequest.opponentName()); final Stone.Color gpReceiverColor = gpRequest.opponentColor(); - // TODO handle expectionns here + // GiteaIssue #4: Exception handling GameView gameStateView = cordaClient.gameProposalCreate( - gpSender, - gpReceiver, - gpReceiverColor, - gpRequest.message() - ); + gpSender, + gpReceiver, + gpReceiverColor, + // gpRequest.board() // GireaIssue #3: use provided board configuration + gpRequest.message()); URI locationOfNewGameProposal = ucb - .path("api/gameproposal/{id}") - .buildAndExpand(gameStateView) - .toUri(); + .path("api/gameproposal/{id}") + .buildAndExpand(gameStateView.uuid()) + .toUri(); return ResponseEntity - .created(locationOfNewGameProposal) - .build(); + .created(locationOfNewGameProposal) + .body(gameStateView); } } \ No newline at end of file diff --git a/webapp/src/components/Game/GameAction/Create.jsx b/webapp/src/components/Game/GameAction/Create.jsx index d32bf4a..c78fff0 100644 --- a/webapp/src/components/Game/GameAction/Create.jsx +++ b/webapp/src/components/Game/GameAction/Create.jsx @@ -7,14 +7,18 @@ export default function Create() { const ctx = Definitions() const onClick = () => { - if (!ctx.hasPlayers) + if (!ctx.hasPlayers) return alert("Choose both black and white players"); if (!ctx.hasCurrentUser) return alert("You must be one of the players"); - + const request = ctx.get_GameProposalRequest() - console.log("TODO: send GameCreateRequest to the server!", request) + + postData("/api/gameproposal", request) + .then((responce) => { + console.log("responce", responce); // JSON data parsed by `data.json()` call + }); } return ( @@ -34,13 +38,13 @@ function Definitions() { const isCurrentUser = data.isCurrentUser const whitePlayerName = ctx.newGame.whitePlayer const blackPlayerName = ctx.newGame.blackPlayer - + const hasPlayers = whitePlayerName !== blackPlayerName && whitePlayerName !== '' && blackPlayerName !== '' const hasCurrentUser = isCurrentUser(whitePlayerName) || isCurrentUser(blackPlayerName) - + const isEnabled = hasPlayers && hasCurrentUser const get_GameProposalRequest = () => { @@ -53,7 +57,7 @@ function Definitions() { message: "let's play a game" } } - + return { hasPlayers, hasCurrentUser, @@ -74,4 +78,21 @@ function get_Opponent(isCurrentUser, whitePlayerName, blackPlayerName) { return ['', ''] } - \ No newline at end of file + +async function postData(url = "", data = {}) { + console.log("POST", url, data) + + const response = await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), // body data type must match "Content-Type" header + }); + + if (response.ok) + return response.json()// parses JSON response into native JavaScript objects + + console.log("recponce", response) + return {} +}