From 9f15747f8c02dad170c27b800226f2fc9c2fd01f Mon Sep 17 00:00:00 2001 From: Okke Harsta Date: Wed, 22 Jan 2025 13:42:05 +0100 Subject: [PATCH] Test and documentation for mobile API endpoint verification code #587 --- .../java/myconext/api/UserController.java | 22 ++++++--- .../myconext/AbstractIntegrationTest.java | 9 +++- .../java/myconext/api/UserControllerTest.java | 8 ---- .../api/UserMobileControllerTest.java | 45 ++++++++++++++++--- 4 files changed, 61 insertions(+), 23 deletions(-) diff --git a/myconext-server/src/main/java/myconext/api/UserController.java b/myconext-server/src/main/java/myconext/api/UserController.java index ad35c355..4696e4ae 100644 --- a/myconext-server/src/main/java/myconext/api/UserController.java +++ b/myconext-server/src/main/java/myconext/api/UserController.java @@ -21,6 +21,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; import jakarta.validation.Valid; +import lombok.Getter; import lombok.SneakyThrows; import myconext.cron.DisposableEmailProviders; import myconext.exceptions.*; @@ -72,9 +73,11 @@ public class UserController implements UserAuthentication { private static final Log LOG = LogFactory.getLog(UserController.class); + @Getter private final UserRepository userRepository; private final AuthenticationRequestRepository authenticationRequestRepository; private final MailBox mailBox; + @Getter private final Manage manage; private final OpenIDConnect openIDConnect; private final String magicLinkUrl; @@ -980,6 +983,13 @@ public ResponseEntity deleteUser(Authentication authentication, return doLogout(request); } + @Operation(summary = "Create verification control code password link", + description = """ + Create a verification control code which users can use to prove their identity at the Service Desk. The + code is also send by email to the user. The required field are firstName, lastName and dayOfBirth. + There are no input validations, if the user's dayOfBirth can not be parsed, then this is solved in + the approval proces in the Serivce Desk + """) @PostMapping("sp/control-code") public ResponseEntity createUserControlCode(Authentication authentication, @RequestBody ControlCode controlCode) { @@ -1006,6 +1016,11 @@ public ResponseEntity createUserControlCode(Authentication authenti return ResponseEntity.ok(controlCode); } + + @Operation(summary = "Delete existing verification control code", + description = """ + Delete an existing verification control code for a user + """) @DeleteMapping("sp/control-code") public ResponseEntity deleteUserControlCode(Authentication authentication) { User user = userFromAuthentication(authentication); @@ -1077,11 +1092,4 @@ private ResponseEntity return404() { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Collections.singletonMap("status", HttpStatus.NOT_FOUND.value())); } - public Manage getManage() { - return manage; - } - - public UserRepository getUserRepository() { - return userRepository; - } } diff --git a/myconext-server/src/test/java/myconext/AbstractIntegrationTest.java b/myconext-server/src/test/java/myconext/AbstractIntegrationTest.java index 0de4e59d..7c493ff7 100644 --- a/myconext-server/src/test/java/myconext/AbstractIntegrationTest.java +++ b/myconext-server/src/test/java/myconext/AbstractIntegrationTest.java @@ -333,11 +333,16 @@ protected Response magicResponse(MagicLinkResponse magicLinkResponse) { return response; } - protected String samlResponse(MagicLinkResponse magicLinkResponse) throws IOException { Response response = magicResponse(magicLinkResponse); - return samlAuthnResponse(response, Optional.empty()); } + protected void clearExternalAccounts(String email) { + User user = userRepository.findOneUserByEmail(email); + user.getLinkedAccounts().clear(); + user.getExternalLinkedAccounts().clear(); + userRepository.save(user); + + } } diff --git a/myconext-server/src/test/java/myconext/api/UserControllerTest.java b/myconext-server/src/test/java/myconext/api/UserControllerTest.java index 75fbb073..12190aef 100644 --- a/myconext-server/src/test/java/myconext/api/UserControllerTest.java +++ b/myconext-server/src/test/java/myconext/api/UserControllerTest.java @@ -1451,12 +1451,4 @@ private String hash() { return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes); } - private void clearExternalAccounts(String email) { - User user = userRepository.findOneUserByEmail(email); - user.getLinkedAccounts().clear(); - user.getExternalLinkedAccounts().clear(); - userRepository.save(user); - - } - } diff --git a/myconext-server/src/test/java/myconext/api/UserMobileControllerTest.java b/myconext-server/src/test/java/myconext/api/UserMobileControllerTest.java index 74bc7420..3912f897 100644 --- a/myconext-server/src/test/java/myconext/api/UserMobileControllerTest.java +++ b/myconext-server/src/test/java/myconext/api/UserMobileControllerTest.java @@ -1,21 +1,22 @@ package myconext.api; import com.github.tomakehurst.wiremock.junit.WireMockRule; +import io.restassured.common.mapper.TypeRef; import io.restassured.http.ContentType; +import lombok.SneakyThrows; import myconext.AbstractIntegrationTest; -import myconext.model.CreateAccount; -import myconext.model.IdentityProvider; -import myconext.model.UpdateUserNameRequest; -import myconext.model.User; +import myconext.model.*; import org.junit.ClassRule; import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import java.io.IOException; import java.util.Map; import static io.restassured.RestAssured.given; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.*; +import static org.junit.Assert.assertNull; public class UserMobileControllerTest extends AbstractIntegrationTest { @@ -139,4 +140,36 @@ public void createEduIDInApp() { .statusCode(302) .header("Location", "http://localhost:3000/client/mobile/created?new=true"); } + + @SneakyThrows + @Test + public void createUserControlCodeMobileApi() { + clearExternalAccounts("jdoe@example.com"); + ControlCode controlCode = new ControlCode("Lee", "Harpers", "01 Mar 1977"); + ControlCode responseControlCode = given() + .accept(ContentType.JSON) + .contentType(ContentType.JSON) + .auth().oauth2(opaqueAccessToken(true, "eduid.nl/mobile")) + .body(controlCode) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .when() + .post("/mobile/api/sp/control-code") + .as(ControlCode.class); + assertEquals(5, responseControlCode.getCode().length()); + User user = userRepository.findOneUserByEmail("jdoe@example.com"); + assertEquals(user.getControlCode().getCode(), responseControlCode.getCode()); + + Map userResponse = given() + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .auth().oauth2(opaqueAccessToken(true, "eduid.nl/mobile")) + .when() + .delete("/mobile/api/sp/control-code") + .as(new TypeRef<>() { + }); + assertFalse(userResponse.containsKey("controlCode")); + + User userFromDB = userRepository.findOneUserByEmail("jdoe@example.com"); + assertNull(userFromDB.getControlCode()); + } + } \ No newline at end of file