From 7eb9fdf3841e3df2ca7d19b136b1f3b55ef9e13e Mon Sep 17 00:00:00 2001 From: Deep Sidhu Date: Fri, 9 Dec 2022 14:37:51 -0600 Subject: [PATCH 1/8] Updated to display error message if setting url manually for sync new remote project and the server returns an error --- .../irida/exceptions/IridaOAuthException.java | 18 +++++++ .../resttemplate/IridaOAuthErrorHandler.java | 9 ++-- .../ria/web/ajax/RemoteAPIAjaxController.java | 8 ++- .../ria/web/services/UIRemoteAPIService.java | 50 +++++++++++++------ src/main/resources/i18n/messages.properties | 4 ++ .../js/apis/remote-api/remote-api.js | 5 +- .../CreateRemoteProjectSyncForm.jsx | 28 +++++++++-- .../web/services/UIRemoteAPIServiceTest.java | 6 ++- 8 files changed, 98 insertions(+), 30 deletions(-) diff --git a/src/main/java/ca/corefacility/bioinformatics/irida/exceptions/IridaOAuthException.java b/src/main/java/ca/corefacility/bioinformatics/irida/exceptions/IridaOAuthException.java index 31a4a2b0682..82b09d04cb6 100644 --- a/src/main/java/ca/corefacility/bioinformatics/irida/exceptions/IridaOAuthException.java +++ b/src/main/java/ca/corefacility/bioinformatics/irida/exceptions/IridaOAuthException.java @@ -1,5 +1,7 @@ package ca.corefacility.bioinformatics.irida.exceptions; +import org.springframework.http.HttpStatus; + import ca.corefacility.bioinformatics.irida.model.RemoteAPI; import ca.corefacility.bioinformatics.irida.model.RemoteAPIToken; @@ -14,6 +16,7 @@ public class IridaOAuthException extends RuntimeException { private static final long serialVersionUID = 5281201199554307578L; private RemoteAPI remoteAPI; + private HttpStatus httpStatusCode; /** * Create a new IridaOAuthException with the given message and service @@ -29,6 +32,13 @@ public IridaOAuthException(String message, RemoteAPI remoteAPI) { this.remoteAPI = remoteAPI; } + public IridaOAuthException(String message, HttpStatus httpStatusCode, RemoteAPI remoteAPI) { + super(message); + this.httpStatusCode = httpStatusCode; + this.remoteAPI = remoteAPI; + + } + /** * Create a new IridaOAuthException with the given message and service * @@ -63,4 +73,12 @@ public RemoteAPI getRemoteAPI() { public void setRemoteAPI(RemoteAPI remoteAPI) { this.remoteAPI = remoteAPI; } + + public HttpStatus getHttpStatusCode() { + return httpStatusCode; + } + + public void setHttpStatusCode(HttpStatus httpStatusCode) { + this.httpStatusCode = httpStatusCode; + } } diff --git a/src/main/java/ca/corefacility/bioinformatics/irida/repositories/remote/resttemplate/IridaOAuthErrorHandler.java b/src/main/java/ca/corefacility/bioinformatics/irida/repositories/remote/resttemplate/IridaOAuthErrorHandler.java index af745a32317..d55a6b3fcd3 100644 --- a/src/main/java/ca/corefacility/bioinformatics/irida/repositories/remote/resttemplate/IridaOAuthErrorHandler.java +++ b/src/main/java/ca/corefacility/bioinformatics/irida/repositories/remote/resttemplate/IridaOAuthErrorHandler.java @@ -30,11 +30,14 @@ public void handleError(ClientHttpResponse response) throws IOException { logger.trace("Checking error type " + statusCode.toString()); switch (statusCode) { case UNAUTHORIZED: - logger.trace("Throwing new IridaOAuthException for this error"); - throw new IridaOAuthException("User is unauthorized for this service", remoteAPI); + logger.trace("Throwing new IridaOAuthException (Unauthorized) for this error"); + throw new IridaOAuthException("User is unauthorized for this service", statusCode, remoteAPI); case FORBIDDEN: + logger.trace("Throwing new IridaOAuthException (Forbidden) for this error"); + throw new IridaOAuthException("User is forbidden from accessing this service", statusCode, remoteAPI); + case NOT_FOUND: logger.trace("Throwing new IridaOAuthException for this error"); - throw new IridaOAuthException("User is unauthorized for this service", remoteAPI); + throw new IridaOAuthException("Resource not found", statusCode, remoteAPI); default: logger.trace("Passing error to superclass"); super.handleError(response); diff --git a/src/main/java/ca/corefacility/bioinformatics/irida/ria/web/ajax/RemoteAPIAjaxController.java b/src/main/java/ca/corefacility/bioinformatics/irida/ria/web/ajax/RemoteAPIAjaxController.java index d82a48923cc..3d256d6b1a5 100644 --- a/src/main/java/ca/corefacility/bioinformatics/irida/ria/web/ajax/RemoteAPIAjaxController.java +++ b/src/main/java/ca/corefacility/bioinformatics/irida/ria/web/ajax/RemoteAPIAjaxController.java @@ -148,13 +148,11 @@ public ResponseEntity> getProjectsForAPI(@PathVariable * @return status of created the new remote project */ @PostMapping("/project") - public ResponseEntity createSynchronizedProject(@RequestBody CreateRemoteProjectRequest request) { + public ResponseEntity createSynchronizedProject(@RequestBody CreateRemoteProjectRequest request, Locale locale) { try { - return ResponseEntity.ok(service.createSynchronizedProject(request)); + return ResponseEntity.ok(new AjaxCreateItemSuccessResponse(service.createSynchronizedProject(request, locale))); } catch (IridaOAuthException e) { - return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new AjaxErrorResponse(e.getMessage())); - } catch (EntityNotFoundException e) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new AjaxErrorResponse(e.getMessage())); + return ResponseEntity.status(e.getHttpStatusCode()).body(new AjaxErrorResponse(e.getMessage())); } } diff --git a/src/main/java/ca/corefacility/bioinformatics/irida/ria/web/services/UIRemoteAPIService.java b/src/main/java/ca/corefacility/bioinformatics/irida/ria/web/services/UIRemoteAPIService.java index 2afa1c551f5..0ba4294cea3 100644 --- a/src/main/java/ca/corefacility/bioinformatics/irida/ria/web/services/UIRemoteAPIService.java +++ b/src/main/java/ca/corefacility/bioinformatics/irida/ria/web/services/UIRemoteAPIService.java @@ -3,9 +3,11 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSource; import org.springframework.stereotype.Component; import ca.corefacility.bioinformatics.irida.exceptions.IridaOAuthException; @@ -14,10 +16,10 @@ import ca.corefacility.bioinformatics.irida.model.project.Project; import ca.corefacility.bioinformatics.irida.model.project.ProjectSyncFrequency; import ca.corefacility.bioinformatics.irida.model.remote.RemoteStatus; -import ca.corefacility.bioinformatics.irida.ria.web.ajax.dto.ajax.AjaxCreateItemSuccessResponse; import ca.corefacility.bioinformatics.irida.ria.web.ajax.dto.remote.CreateRemoteProjectRequest; import ca.corefacility.bioinformatics.irida.ria.web.ajax.dto.remote.RemoteAPIModel; import ca.corefacility.bioinformatics.irida.ria.web.ajax.dto.remote.RemoteProjectModel; + import ca.corefacility.bioinformatics.irida.service.ProjectService; import ca.corefacility.bioinformatics.irida.service.RemoteAPIService; import ca.corefacility.bioinformatics.irida.service.RemoteAPITokenService; @@ -33,13 +35,16 @@ public class UIRemoteAPIService { private final ProjectRemoteService projectRemoteService; private final ProjectService projectService; + private MessageSource messageSource; + @Autowired public UIRemoteAPIService(RemoteAPIService remoteAPIService, RemoteAPITokenService tokenService, - ProjectRemoteService projectRemoteService, ProjectService projectService) { + ProjectRemoteService projectRemoteService, ProjectService projectService, MessageSource messageSource) { this.remoteAPIService = remoteAPIService; this.tokenService = tokenService; this.projectRemoteService = projectRemoteService; this.projectService = projectService; + this.messageSource = messageSource; } /** @@ -114,19 +119,34 @@ public List getProjectsForAPI(Long remoteId) { * @param request Details about the remote project to synchronize * @return the result of adding the new remote project */ - public AjaxCreateItemSuccessResponse createSynchronizedProject(CreateRemoteProjectRequest request) { - Project project = projectRemoteService.read(request.getUrl()); - project.setId(null); - if (request.getFrequency() - .equals(ProjectSyncFrequency.NEVER)) { - project.getRemoteStatus() - .setSyncStatus(RemoteStatus.SyncStatus.UNSYNCHRONIZED); - } else { - project.getRemoteStatus() - .setSyncStatus(RemoteStatus.SyncStatus.MARKED); + public Long createSynchronizedProject(CreateRemoteProjectRequest request, Locale locale) { + try { + Project project = projectRemoteService.read(request.getUrl()); + project.setId(null); + if (request.getFrequency().equals(ProjectSyncFrequency.NEVER)) { + project.getRemoteStatus().setSyncStatus(RemoteStatus.SyncStatus.UNSYNCHRONIZED); + } else { + project.getRemoteStatus().setSyncStatus(RemoteStatus.SyncStatus.MARKED); + } + project.setSyncFrequency(request.getFrequency()); + project = projectService.create(project); + return project.getId(); + } catch(IridaOAuthException e) { + String errorMessage; + switch (e.getHttpStatusCode()) { + case UNAUTHORIZED: + errorMessage = messageSource.getMessage("IridaOAuthErrorHandler.unauthorized", new Object[] {}, locale); + throw new IridaOAuthException(errorMessage, e.getHttpStatusCode(), remoteAPIService.getRemoteAPIForUrl(request.getUrl())); + case FORBIDDEN: + errorMessage = messageSource.getMessage("IridaOAuthErrorHandler.forbidden", new Object[] {}, locale); + throw new IridaOAuthException(errorMessage, e.getHttpStatusCode(), remoteAPIService.getRemoteAPIForUrl(request.getUrl())); + case NOT_FOUND: + errorMessage = messageSource.getMessage("IridaOAuthErrorHandler.notFound", new Object[] {}, locale); + throw new IridaOAuthException(errorMessage, e.getHttpStatusCode(), remoteAPIService.getRemoteAPIForUrl(request.getUrl())); + default: + errorMessage = e.getMessage(); + throw new IridaOAuthException(errorMessage, e.getHttpStatusCode(), remoteAPIService.getRemoteAPIForUrl(request.getUrl())); + } } - project.setSyncFrequency(request.getFrequency()); - project = projectService.create(project); - return new AjaxCreateItemSuccessResponse(project.getId()); } } diff --git a/src/main/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties index 5386fe8b778..aa9fbb6eb15 100644 --- a/src/main/resources/i18n/messages.properties +++ b/src/main/resources/i18n/messages.properties @@ -3023,3 +3023,7 @@ AnalysisState.ERROR=Error # InputWithOptions # #=========================================================================================# InputWithOptions.required={0} is required to run this pipeline. Please select one of the options. + +IridaOAuthErrorHandler.unauthorized=User is unauthorized for this service +IridaOAuthErrorHandler.forbidden=Access denied. User is forbidden from accessing this service +IridaOAuthErrorHandler.notFound=Resource not found. A resource with the given identifier could not be found \ No newline at end of file diff --git a/src/main/webapp/resources/js/apis/remote-api/remote-api.js b/src/main/webapp/resources/js/apis/remote-api/remote-api.js index 34f25dc5792..8f5bc53f1ac 100644 --- a/src/main/webapp/resources/js/apis/remote-api/remote-api.js +++ b/src/main/webapp/resources/js/apis/remote-api/remote-api.js @@ -59,5 +59,8 @@ export function getProjectsForAPI({ id }) { export function createSynchronizedProject({ url, frequency }) { return axios .post(`${BASE_URL}/project`, { url, frequency }) - .then(({ data }) => data); + .then(({ data }) => data) + .catch((error) => { + return Promise.reject(error.response.data.error); + }); } diff --git a/src/main/webapp/resources/js/components/remote-api/CreateRemoteProjectSyncForm.jsx b/src/main/webapp/resources/js/components/remote-api/CreateRemoteProjectSyncForm.jsx index 51b1206437d..462ede92e0c 100644 --- a/src/main/webapp/resources/js/components/remote-api/CreateRemoteProjectSyncForm.jsx +++ b/src/main/webapp/resources/js/components/remote-api/CreateRemoteProjectSyncForm.jsx @@ -18,6 +18,8 @@ import { SyncFrequencySelect } from "./SyncFrequencySelect"; export function CreateRemoteProjectSyncForm() { const [apis, setApis] = useState([]); const [selectedApi, setSelectedApi] = useState(); + const [newRemoteProjectUrlError, setNewRemoteProjectUrlError] = + useState(null); const [projects, setProjects] = useState([]); const [connected, setConnected] = useState(); const [manual, setManual] = useState(false); @@ -53,12 +55,15 @@ export function CreateRemoteProjectSyncForm() { const createRemote = () => { form.validateFields().then(({ frequency, url }) => { + setNewRemoteProjectUrlError(null); createSynchronizedProject({ url, frequency, - }).then( - ({ id }) => (window.location.href = setBaseUrl(`/projects/${id}`)) - ); + }) + .then( + ({ id }) => (window.location.href = setBaseUrl(`/projects/${id}`)) + ) + .catch((error) => setNewRemoteProjectUrlError(error)); }); }; @@ -106,6 +111,10 @@ export function CreateRemoteProjectSyncForm() { /> {i18n("NewProjectSync.remoteUrl")} - setManual(e.target.checked)}> + { + setManual(e.target.checked); + setNewRemoteProjectUrlError(null); + }} + > {i18n("NewProjectSync.remoteUrl.manual")} {i18n("NewProjectSync.url.help")}} @@ -125,7 +139,11 @@ export function CreateRemoteProjectSyncForm() { } name="url" > - + setNewRemoteProjectUrlError(null)} + /> diff --git a/src/test/java/ca/corefacility/bioinformatics/irida/ria/unit/web/services/UIRemoteAPIServiceTest.java b/src/test/java/ca/corefacility/bioinformatics/irida/ria/unit/web/services/UIRemoteAPIServiceTest.java index 345735c468a..5026c87b017 100644 --- a/src/test/java/ca/corefacility/bioinformatics/irida/ria/unit/web/services/UIRemoteAPIServiceTest.java +++ b/src/test/java/ca/corefacility/bioinformatics/irida/ria/unit/web/services/UIRemoteAPIServiceTest.java @@ -6,6 +6,7 @@ import org.apache.commons.lang3.time.DateUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.context.MessageSource; import ca.corefacility.bioinformatics.irida.exceptions.IridaOAuthException; import ca.corefacility.bioinformatics.irida.model.RemoteAPI; @@ -31,6 +32,8 @@ public class UIRemoteAPIServiceTest { private ProjectService projectService; private UIRemoteAPIService service; + private MessageSource messageSource; + private final long REMOTE_ID_WITH_TOKEN = 1L; private final String REMOTE_CLIENT_ID_WITH_TOKEN = "with_token"; private final long REMOTE_ID_WITH_EXPIRED_TOKEN = 2L; @@ -46,7 +49,8 @@ public void setUp() { this.tokenService = mock(RemoteAPITokenService.class); this.projectRemoteService = mock(ProjectRemoteService.class); this.projectService = mock(ProjectService.class); - this.service = new UIRemoteAPIService(remoteAPIService, tokenService, projectRemoteService, projectService); + this.messageSource = mock(MessageSource.class); + this.service = new UIRemoteAPIService(remoteAPIService, tokenService, projectRemoteService, projectService, messageSource); // Valid token RemoteAPI validAPI = createFakeRemoteAPI(REMOTE_CLIENT_ID_WITH_TOKEN); From e29fe8a70fb04d4ea064b70a6aaf89fb5f5a0977 Mon Sep 17 00:00:00 2001 From: Deep Sidhu Date: Fri, 9 Dec 2022 14:43:10 -0600 Subject: [PATCH 2/8] Updated CHANGELOG --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 950fc531c5d..d49413b5293 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog +## [22.09.5] - Unreleased +* [Developer/UI]: Updated synchronize new remote project page to display http errors when setting the url manually and an error is encountered. See [PR 1433](https://github.com/phac-nml/irida/pull/1431) + ## [22.09.4] - 2022/11/14 * [REST]: Fixed issue with project/samples api response missing samples when a sample has a default sequencing object. See [PR 1413](https://github.com/phac-nml/irida/pull/1413) From 3c62b5679993d5808e1a9617da2c9922830dcc89 Mon Sep 17 00:00:00 2001 From: Deep Sidhu Date: Tue, 13 Dec 2022 13:17:14 -0600 Subject: [PATCH 3/8] Added tests --- .../CreateRemoteProjectSyncForm.jsx | 1 + .../pages/projects/ProjectSyncPage.java | 34 ++++++++++ .../pages/remoteapi/RemoteAPIsPage.java | 7 +- .../projects/ProjectSyncPageIT.java | 67 ++++++++++++++++++- .../irida/ria/web/ProjectsPageIT.xml | 2 + 5 files changed, 107 insertions(+), 4 deletions(-) diff --git a/src/main/webapp/resources/js/components/remote-api/CreateRemoteProjectSyncForm.jsx b/src/main/webapp/resources/js/components/remote-api/CreateRemoteProjectSyncForm.jsx index 462ede92e0c..3cf767732f6 100644 --- a/src/main/webapp/resources/js/components/remote-api/CreateRemoteProjectSyncForm.jsx +++ b/src/main/webapp/resources/js/components/remote-api/CreateRemoteProjectSyncForm.jsx @@ -125,6 +125,7 @@ export function CreateRemoteProjectSyncForm() { {i18n("NewProjectSync.remoteUrl")} { setManual(e.target.checked); setNewRemoteProjectUrlError(null); diff --git a/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/pages/projects/ProjectSyncPage.java b/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/pages/projects/ProjectSyncPage.java index a99624e67b7..af91e34e7a7 100644 --- a/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/pages/projects/ProjectSyncPage.java +++ b/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/pages/projects/ProjectSyncPage.java @@ -1,6 +1,7 @@ package ca.corefacility.bioinformatics.irida.ria.integration.pages.projects; import java.time.Duration; +import java.util.List; import org.openqa.selenium.By; import org.openqa.selenium.Keys; @@ -78,4 +79,37 @@ public void submitProject() { waitForTime(500); } + public boolean isResourceNotFoundErrorMessageDisplayed() { + List elements = driver.findElements(By.className("ant-form-item-explain-error")); + + if(elements.size() == 1) { + return elements.get(0).getText().contains("Resource not found"); + } + return false; + } + + public boolean isAccessDeniedErrorMessageDisplayed() { + List elements = driver.findElements(By.className("ant-form-item-explain-error")); + + if(elements.size() == 1) { + return elements.get(0).getText().contains("Access denied"); + } + return false; + } + + public void clickSetUrlManuallyCheckbox() { + WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); + WebElement element = driver.findElement(By.className("t-remote-project-url-checkbox")); + wait.until(ExpectedConditions.elementToBeClickable(element)); + element.click(); + waitForTime(500); + } + + public void setRemoteProjectUrl(String projectUrl) { + WebElement element = driver.findElement(By.className("t-project-url")); + element.sendKeys(Keys.CONTROL + "a", Keys.DELETE); + element.sendKeys(projectUrl); + waitForTime(500); + } + } diff --git a/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/pages/remoteapi/RemoteAPIsPage.java b/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/pages/remoteapi/RemoteAPIsPage.java index e6570724486..7393d1ac40a 100644 --- a/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/pages/remoteapi/RemoteAPIsPage.java +++ b/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/pages/remoteapi/RemoteAPIsPage.java @@ -18,7 +18,7 @@ public class RemoteAPIsPage extends AbstractPage { private static final String RELATIVE_URL = "remote_api"; - @FindBy(css = ".t-remoteapi-table table") + @FindBy(className = "t-remoteapi-table") private WebElement table; @FindBy(className = "t-add-remote-api-btn") @@ -120,7 +120,10 @@ public void connectToRemoteAPI(String clientName) { for (WebElement row : rows) { WebElement nameCell = row.findElement(By.className("t-api-name")); if (nameCell != null && nameCell.getText().equals(clientName)) { - row.findElement(By.className("t-remote-status-connect")).click(); + WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(2)); + WebElement connectBtn = row.findElement(By.className("t-remote-status-connect")); + wait.until(ExpectedConditions.elementToBeClickable(connectBtn)); + connectBtn.click(); waitForTime(400); clickAuthorize(); } diff --git a/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/projects/ProjectSyncPageIT.java b/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/projects/ProjectSyncPageIT.java index df6b737f1a7..c84b41a4b32 100644 --- a/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/projects/ProjectSyncPageIT.java +++ b/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/projects/ProjectSyncPageIT.java @@ -7,12 +7,12 @@ import ca.corefacility.bioinformatics.irida.ria.integration.pages.admin.AdminClientsPage; import ca.corefacility.bioinformatics.irida.ria.integration.pages.projects.ProjectDetailsPage; import ca.corefacility.bioinformatics.irida.ria.integration.pages.projects.ProjectSyncPage; +import ca.corefacility.bioinformatics.irida.ria.integration.pages.remoteapi.RemoteAPIsPage; import ca.corefacility.bioinformatics.irida.ria.integration.utilities.RemoteApiUtilities; import com.github.springtestdbunit.annotation.DatabaseSetup; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.*; @DatabaseSetup("/ca/corefacility/bioinformatics/irida/ria/web/ProjectsPageIT.xml") public class ProjectSyncPageIT extends AbstractIridaUIITChromeDriver { @@ -48,4 +48,67 @@ public void testSyncProject() { String dataProjectName = projectDetailsPage.getProjectName(); assertEquals(dataProjectName, name, "Should be on the remote project page"); } + + @Test + public void testSyncProjectNotExist() { + LoginPage.loginAsAdmin(driver()); + + //create the oauth client + String redirectLocation = RemoteApiUtilities.getRedirectLocation(); + clientsPage = AdminClientsPage.goTo(driver()); + clientsPage.createClientWithDetails(clientId, "authorization_code", redirectLocation, AdminClientsPage.READ_YES, + AdminClientsPage.WRITE_NO); + clientSecret = clientsPage.getClientSecret(clientId); + RemoteApiUtilities.addRemoteApi(driver(), clientId, clientSecret); + LoginPage.logout(driver()); + + LoginPage.loginAsManager(driver()); + + RemoteAPIsPage remoteAPIsPage = RemoteAPIsPage.goToUserPage(driver()); + remoteAPIsPage.connectToRemoteAPI("new name"); + + page = ProjectSyncPage.goTo(driver()); + page.selectApi(0); + final String name = "project"; + page.selectProjectInListing(name); + + page.clickSetUrlManuallyCheckbox(); + String url = page.getProjectUrl() + "11"; + page.setRemoteProjectUrl(url); + page.submitProject(); + + // The project does not exist so a resource not found error should be displayed + assertTrue(page.isResourceNotFoundErrorMessageDisplayed()); + } + + @Test + public void testSyncProjectAccessDenied() { + LoginPage.loginAsAdmin(driver()); + + //create the oauth client + String redirectLocation = RemoteApiUtilities.getRedirectLocation(); + clientsPage = AdminClientsPage.goTo(driver()); + clientsPage.createClientWithDetails(clientId, "authorization_code", redirectLocation, AdminClientsPage.READ_YES, + AdminClientsPage.WRITE_NO); + clientSecret = clientsPage.getClientSecret(clientId); + RemoteApiUtilities.addRemoteApi(driver(), clientId, clientSecret); + LoginPage.logout(driver()); + + LoginPage.loginAsManager(driver()); + + RemoteAPIsPage remoteAPIsPage = RemoteAPIsPage.goToUserPage(driver()); + remoteAPIsPage.connectToRemoteAPI("new name"); + page = ProjectSyncPage.goTo(driver()); + page.selectApi(0); + final String name = "project"; + page.selectProjectInListing(name); + + page.clickSetUrlManuallyCheckbox(); + String url = page.getProjectUrl().replaceFirst("[^/]*$", "9"); + page.setRemoteProjectUrl(url); + page.submitProject(); + + // The project exists but the currently logged in user is not on the project, so an access denied error should be displayed + assertTrue(page.isAccessDeniedErrorMessageDisplayed()); + } } diff --git a/src/test/resources/ca/corefacility/bioinformatics/irida/ria/web/ProjectsPageIT.xml b/src/test/resources/ca/corefacility/bioinformatics/irida/ria/web/ProjectsPageIT.xml index 676a15cea9c..dd1d84d1939 100644 --- a/src/test/resources/ca/corefacility/bioinformatics/irida/ria/web/ProjectsPageIT.xml +++ b/src/test/resources/ca/corefacility/bioinformatics/irida/ria/web/ProjectsPageIT.xml @@ -16,6 +16,7 @@ + @@ -26,6 +27,7 @@ + From 7970ade166ced257ac9de6624172a1a6ff11a452 Mon Sep 17 00:00:00 2001 From: Deep Sidhu Date: Tue, 13 Dec 2022 15:24:10 -0600 Subject: [PATCH 4/8] Updated assertEquals statements --- .../irida/ria/integration/projects/ProjectsPageIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/projects/ProjectsPageIT.java b/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/projects/ProjectsPageIT.java index 98e2e8f4a83..39369ce4fe5 100644 --- a/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/projects/ProjectsPageIT.java +++ b/src/test/java/ca/corefacility/bioinformatics/irida/ria/integration/projects/ProjectsPageIT.java @@ -28,7 +28,7 @@ public void testProjectsPageAsAdmin() { ProjectsPage page = ProjectsPage.goToProjectsPage(driver(), true); checkTranslations(page, ImmutableList.of("projects"), "Projects\nCreate New Project"); - assertEquals(8, page.getNumberOfProjects(), "Should be 8 projects"); + assertEquals(9, page.getNumberOfProjects(), "Should be 9 projects"); List projectNames = page.getProjectsSortListByColumnName(); assertFalse(Ordering.natural().isOrdered(projectNames), "Projects name should not be sorted originally"); @@ -56,7 +56,7 @@ public void testProjectsPageAsUser() { page = ProjectsPage.goToProjectsPage(driver(), false); checkTranslations(page, ImmutableList.of("projects"), "Projects\nCreate New Project"); - assertEquals(2, page.getNumberOfProjects(), "Should be 2 projects on the page"); + assertEquals(3, page.getNumberOfProjects(), "Should be 3 projects on the page"); assertTrue(page.createNewButtonVisible(), "There should be a Create New Project button visible"); } From 62f27bc896066cecdd6c76662d39b333a79200b1 Mon Sep 17 00:00:00 2001 From: deepsidhu85 Date: Wed, 14 Dec 2022 08:39:54 -0600 Subject: [PATCH 5/8] Updated translations --- src/main/resources/i18n/messages.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties index aa9fbb6eb15..07328ba1f19 100644 --- a/src/main/resources/i18n/messages.properties +++ b/src/main/resources/i18n/messages.properties @@ -3024,6 +3024,6 @@ AnalysisState.ERROR=Error #=========================================================================================# InputWithOptions.required={0} is required to run this pipeline. Please select one of the options. -IridaOAuthErrorHandler.unauthorized=User is unauthorized for this service -IridaOAuthErrorHandler.forbidden=Access denied. User is forbidden from accessing this service -IridaOAuthErrorHandler.notFound=Resource not found. A resource with the given identifier could not be found \ No newline at end of file +IridaOAuthErrorHandler.unauthorized=User is unauthorized for this resource +IridaOAuthErrorHandler.forbidden=Access denied. User is forbidden from accessing this resource +IridaOAuthErrorHandler.notFound=Resource not found. A resource with the given identifier could not be found From 4d292bf1bc247ddd4230213ae0fed6957cf444a8 Mon Sep 17 00:00:00 2001 From: deepsidhu85 Date: Wed, 14 Dec 2022 08:43:40 -0600 Subject: [PATCH 6/8] Updated exception text --- .../remote/resttemplate/IridaOAuthErrorHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/ca/corefacility/bioinformatics/irida/repositories/remote/resttemplate/IridaOAuthErrorHandler.java b/src/main/java/ca/corefacility/bioinformatics/irida/repositories/remote/resttemplate/IridaOAuthErrorHandler.java index d55a6b3fcd3..5d8e31567c4 100644 --- a/src/main/java/ca/corefacility/bioinformatics/irida/repositories/remote/resttemplate/IridaOAuthErrorHandler.java +++ b/src/main/java/ca/corefacility/bioinformatics/irida/repositories/remote/resttemplate/IridaOAuthErrorHandler.java @@ -31,10 +31,10 @@ public void handleError(ClientHttpResponse response) throws IOException { switch (statusCode) { case UNAUTHORIZED: logger.trace("Throwing new IridaOAuthException (Unauthorized) for this error"); - throw new IridaOAuthException("User is unauthorized for this service", statusCode, remoteAPI); + throw new IridaOAuthException("User is unauthorized for this resource", statusCode, remoteAPI); case FORBIDDEN: logger.trace("Throwing new IridaOAuthException (Forbidden) for this error"); - throw new IridaOAuthException("User is forbidden from accessing this service", statusCode, remoteAPI); + throw new IridaOAuthException("User is forbidden from accessing this resource", statusCode, remoteAPI); case NOT_FOUND: logger.trace("Throwing new IridaOAuthException for this error"); throw new IridaOAuthException("Resource not found", statusCode, remoteAPI); From 5ed3b0c7e430a6ab3756ae539d5f88f368259545 Mon Sep 17 00:00:00 2001 From: deepsidhu85 Date: Wed, 14 Dec 2022 08:57:01 -0600 Subject: [PATCH 7/8] Reverting text --- .../remote/resttemplate/IridaOAuthErrorHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ca/corefacility/bioinformatics/irida/repositories/remote/resttemplate/IridaOAuthErrorHandler.java b/src/main/java/ca/corefacility/bioinformatics/irida/repositories/remote/resttemplate/IridaOAuthErrorHandler.java index 5d8e31567c4..4aaa2a9720c 100644 --- a/src/main/java/ca/corefacility/bioinformatics/irida/repositories/remote/resttemplate/IridaOAuthErrorHandler.java +++ b/src/main/java/ca/corefacility/bioinformatics/irida/repositories/remote/resttemplate/IridaOAuthErrorHandler.java @@ -31,7 +31,7 @@ public void handleError(ClientHttpResponse response) throws IOException { switch (statusCode) { case UNAUTHORIZED: logger.trace("Throwing new IridaOAuthException (Unauthorized) for this error"); - throw new IridaOAuthException("User is unauthorized for this resource", statusCode, remoteAPI); + throw new IridaOAuthException("User is unauthorized for this service", statusCode, remoteAPI); case FORBIDDEN: logger.trace("Throwing new IridaOAuthException (Forbidden) for this error"); throw new IridaOAuthException("User is forbidden from accessing this resource", statusCode, remoteAPI); From f1f396e3dfa534b47a7bf9e0789e5713870b12e1 Mon Sep 17 00:00:00 2001 From: deepsidhu85 Date: Wed, 14 Dec 2022 08:59:00 -0600 Subject: [PATCH 8/8] Reverted translation text --- src/main/resources/i18n/messages.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties index 07328ba1f19..7155178222c 100644 --- a/src/main/resources/i18n/messages.properties +++ b/src/main/resources/i18n/messages.properties @@ -3024,6 +3024,6 @@ AnalysisState.ERROR=Error #=========================================================================================# InputWithOptions.required={0} is required to run this pipeline. Please select one of the options. -IridaOAuthErrorHandler.unauthorized=User is unauthorized for this resource +IridaOAuthErrorHandler.unauthorized=User is unauthorized for this service IridaOAuthErrorHandler.forbidden=Access denied. User is forbidden from accessing this resource IridaOAuthErrorHandler.notFound=Resource not found. A resource with the given identifier could not be found