diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/AupSignatureController.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/AupSignatureController.java index 3303fc984..f7db70d31 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/AupSignatureController.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/AupSignatureController.java @@ -18,13 +18,17 @@ import java.util.Date; import java.util.function.Supplier; +import javax.security.auth.login.AccountNotFoundException; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseStatus; @@ -62,18 +66,18 @@ public AupSignatureController(AupSignatureConverter conv, AccountUtils utils, this.eventPublisher = publisher; } - private Supplier accountNotFoundException(String message) { - return () -> new IllegalStateException(message); + private Supplier accountNotFoundException(String message) { + return () -> new AccountNotFoundException(message); } - - private Supplier signatureNotFound(IamAccount account){ + + private Supplier signatureNotFound(IamAccount account) { return () -> new AupSignatureNotFoundError(account); } @RequestMapping(value = "/iam/aup/signature", method = RequestMethod.POST) - @PreAuthorize("#oauth2.hasScope('iam:admin.write') or #iam.hasDashboardRole('ROLE_USER')") + @PreAuthorize("#iam.hasDashboardRole('ROLE_USER')") @ResponseStatus(code = HttpStatus.CREATED) - public void signAup() { + public void signAup() throws AccountNotFoundException { IamAccount account = accountUtils.getAuthenticatedUserAccount() .orElseThrow(accountNotFoundException("Account not found for authenticated user")); @@ -84,28 +88,38 @@ public void signAup() { } @RequestMapping(value = "/iam/aup/signature", method = RequestMethod.GET) - @PreAuthorize("#oauth2.hasScope('iam:admin.read') or #iam.hasDashboardRole('ROLE_USER')") - public AupSignatureDTO getSignature() { + @PreAuthorize("#iam.hasDashboardRole('ROLE_USER')") + public AupSignatureDTO getSignature() throws AccountNotFoundException { IamAccount account = accountUtils.getAuthenticatedUserAccount() .orElseThrow(accountNotFoundException("Account not found for authenticated user")); - IamAupSignature sig = signatureRepo.findSignatureForAccount(account) - .orElseThrow(signatureNotFound(account)); + IamAupSignature sig = + signatureRepo.findSignatureForAccount(account).orElseThrow(signatureNotFound(account)); return signatureConverter.dtoFromEntity(sig); } @RequestMapping(value = "/iam/aup/signature/{accountId}", method = RequestMethod.GET) @PreAuthorize("#oauth2.hasScope('iam:admin.read') or #iam.hasAnyDashboardRole('ROLE_ADMIN', 'ROLE_GM') or #iam.isUser(#accountId)") - public AupSignatureDTO getSignatureForAccount(@PathVariable String accountId) { + public AupSignatureDTO getSignatureForAccount(@PathVariable String accountId) throws AccountNotFoundException { IamAccount account = accountUtils.getByAccountId(accountId) .orElseThrow(accountNotFoundException("Account not found for id: " + accountId)); - - IamAupSignature sig = signatureRepo.findSignatureForAccount(account) - .orElseThrow(signatureNotFound(account)); - return signatureConverter.dtoFromEntity(sig); + IamAupSignature sig = + signatureRepo.findSignatureForAccount(account).orElseThrow(signatureNotFound(account)); + + return signatureConverter.dtoFromEntity(sig); + } + + @RequestMapping(value = "/iam/aup/signature/{accountId}", method = RequestMethod.PATCH) + @PreAuthorize("#oauth2.hasScope('iam:admin.write')") + public void setSignatureForAccount(@PathVariable String accountId, + @RequestBody @Validated AupSignatureDTO dto) throws AccountNotFoundException { + IamAccount account = accountUtils.getByAccountId(accountId) + .orElseThrow(accountNotFoundException("Account not found for id: " + accountId)); + + signatureRepo.createSignatureForAccount(account, dto.getSignatureTime()); } @ResponseStatus(value = HttpStatus.NOT_FOUND) @@ -113,4 +127,10 @@ public AupSignatureDTO getSignatureForAccount(@PathVariable String accountId) { public ErrorDTO notFoundError(Exception ex) { return ErrorDTO.fromString(ex.getMessage()); } + + @ResponseStatus(value = HttpStatus.NOT_FOUND) + @ExceptionHandler(AccountNotFoundException.class) + public ErrorDTO accountNotFoundError(Exception ex) { + return ErrorDTO.fromString(ex.getMessage()); + } } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupSignatureIntegrationTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupSignatureIntegrationTests.java index 4ac0802a5..d094be313 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupSignatureIntegrationTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupSignatureIntegrationTests.java @@ -15,12 +15,13 @@ */ package it.infn.mw.iam.test.api.aup; -import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -47,6 +48,7 @@ import it.infn.mw.iam.test.util.DateEqualModulo1Second; import it.infn.mw.iam.test.util.MockTimeProvider; import it.infn.mw.iam.test.util.WithAnonymousUser; +import it.infn.mw.iam.test.util.WithMockOAuthUser; import it.infn.mw.iam.test.util.annotation.IamMockMvcIntegrationTest; import it.infn.mw.iam.test.util.oauth.MockOAuth2Filter; @@ -235,4 +237,43 @@ public void adminUserCanSeeOtherUserAup() throws Exception { get("/iam/aup/signature/" + TEST_USER_UUID).with(user("admin").roles("USER", "ADMIN"))) .andExpect(status().isOk()); } + + @Test + @WithMockOAuthUser(user = "admin", authorities = "ROLE_ADMIN", scopes = {"iam:admin.read", "iam:admin.write"}) + public void updateAupWithRightScope() throws Exception { + IamAup aup = buildDefaultAup(); + aupRepo.save(aup); + + mvc.perform(get("/iam/aup/signature/{accountId}", TEST_USER_UUID)) + .andExpect(status().isNotFound()) + .andExpect(jsonPath("$.error", equalTo("AUP signature not found for user 'test'"))); + + Date newEndTime = new Date(); + AupSignatureDTO dto = new AupSignatureDTO(); + dto.setSignatureTime(newEndTime); + + mvc + .perform(patch("/iam/aup/signature/{accountId}", TEST_USER_UUID).content(mapper.writeValueAsString(dto)) + .contentType(APPLICATION_JSON)) + .andExpect(OK); + + String sigString = mvc.perform(get("/iam/aup/signature/{accountId}", TEST_USER_UUID)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.aup").exists()) + .andExpect(jsonPath("$.account.uuid").exists()) + .andExpect(jsonPath("$.account.username", equalTo("test"))) + .andExpect(jsonPath("$.account.name", equalTo("Test User"))) + .andExpect(jsonPath("$.signatureTime").exists()) + .andReturn() + .getResponse() + .getContentAsString(); + + AupSignatureDTO sig = mapper.readValue(sigString, AupSignatureDTO.class); + assertThat(sig.getSignatureTime(), new DateEqualModulo1Second(newEndTime)); + + mvc.perform(get("/iam/aup/signature/{accountId}", "1234")) + .andExpect(status().isNotFound()) + .andExpect(jsonPath("$.error", equalTo("Account not found for id: 1234"))); + + } }