diff --git a/api/src/components/publicationVersion/controller.ts b/api/src/components/publicationVersion/controller.ts index 2c51ab7a6..3e03fa604 100644 --- a/api/src/components/publicationVersion/controller.ts +++ b/api/src/components/publicationVersion/controller.ts @@ -34,9 +34,8 @@ export const get = async ( return response.json(200, publicationVersion); } - return response.json(404, { - message: - 'Publication version is either not found, or you do not have permissions to view it in its current state.' + return response.json(403, { + message: 'You do not have permission to view this publication version.' }); } catch (err) { console.log(err); diff --git a/e2e/tests/LoggedIn/publish.e2e.spec.ts b/e2e/tests/LoggedIn/publish.e2e.spec.ts index 980f4172b..9fa4605be 100644 --- a/e2e/tests/LoggedIn/publish.e2e.spec.ts +++ b/e2e/tests/LoggedIn/publish.e2e.spec.ts @@ -1997,7 +1997,7 @@ test.describe('Publication flow + co-authors', () => { page.waitForResponse( (response) => response.request().method() === 'GET' && - response.url().includes(`/publication-versions/latest`) && + response.url().includes(`/publication-versions/`) && response.ok() ) ]); diff --git a/e2e/tests/helpers.ts b/e2e/tests/helpers.ts index 2db5df4a3..08e6dfa93 100644 --- a/e2e/tests/helpers.ts +++ b/e2e/tests/helpers.ts @@ -189,7 +189,7 @@ export const clickFirstPublication = async (page: Page): Promise => { await firstPublication.click(); // expect URL to contain publication path - await expect(page).toHaveURL(`${UI_BASE}${firstPublicationPath}`); + await expect(page).toHaveURL(`${UI_BASE}${firstPublicationPath}/versions/latest`); }; export const testDateInput = async (page: Page, dateFromInput: Locator, dateToInput: Locator): Promise => { diff --git a/ui/src/pages/publications/[id]/index.tsx b/ui/src/pages/publications/[id]/index.tsx index feced6267..c1fce4bd2 100755 --- a/ui/src/pages/publications/[id]/index.tsx +++ b/ui/src/pages/publications/[id]/index.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useMemo } from 'react'; import parse from 'html-react-parser'; import Head from 'next/head'; import useSWR from 'swr'; -import axios from 'axios'; +import axios, { AxiosResponse } from 'axios'; import * as OutlineIcons from '@heroicons/react/24/outline'; import * as api from '@api'; @@ -58,7 +58,10 @@ export const getServerSideProps: Types.GetServerSideProps = async (context) => { // fetch data concurrently const promises: [ - Promise, + Promise< + | { publicationVersion: Interfaces.PublicationVersion; versionRequestError: null } + | { publicationVersion: null; versionRequestError: { status: number; message: string } } + >, Promise, Promise, Promise, @@ -66,8 +69,14 @@ export const getServerSideProps: Types.GetServerSideProps = async (context) => { ] = [ api .get(`${Config.endpoints.publications}/${requestedId}/publication-versions/latest`, token) - .then((res) => res.data) - .catch((error) => console.log(error)), + .then((res) => ({ publicationVersion: res.data, versionRequestError: null })) + .catch((error) => { + console.log(error); + const status = error.response.status; + const message = error.response.data.message; + + return { publicationVersion: null, versionRequestError: { status, message } }; + }), api .get(`${Config.endpoints.bookmarks}?type=PUBLICATION&entityId=${requestedId}`, token) .then((res) => res.data) @@ -87,31 +96,47 @@ export const getServerSideProps: Types.GetServerSideProps = async (context) => { ]; const [ - publicationVersion, + { publicationVersion, versionRequestError }, bookmarks = [], directLinks = { publication: null, linkedTo: [], linkedFrom: [] }, flags = [], topics = [] ] = await Promise.all(promises); - if (!publicationVersion) { + if (versionRequestError) { + const status = versionRequestError.status; + if (status === 404 || (token && status === 403)) { + return { + notFound: true + }; + } else if (status === 403) { + return { + redirect: { + destination: `${Config.urls.orcidLogin.path}&state=${encodeURIComponent(context.resolvedUrl)}`, + permanent: false + } + }; + } + } + + if (publicationVersion) { + return { + props: { + publicationVersion, + userToken: token || '', + bookmarkId: bookmarks.length ? bookmarks[0].id : null, + publicationId: publicationVersion.publication.id, + protectedPage: ['LOCKED', 'DRAFT'].includes(publicationVersion.currentStatus), + directLinks, + flags, + topics + } + }; + } else { return { notFound: true }; } - - return { - props: { - publicationVersion, - userToken: token || '', - bookmarkId: bookmarks.length ? bookmarks[0].id : null, - publicationId: publicationVersion.publication.id, - protectedPage: ['LOCKED', 'DRAFT'].includes(publicationVersion.currentStatus), - directLinks, - flags, - topics - } - }; }; type Props = { diff --git a/ui/src/pages/publications/[id]/versions/[versionId].tsx b/ui/src/pages/publications/[id]/versions/[versionId].tsx old mode 100644 new mode 100755 index d50df119a..f970b41a6 --- a/ui/src/pages/publications/[id]/versions/[versionId].tsx +++ b/ui/src/pages/publications/[id]/versions/[versionId].tsx @@ -64,7 +64,10 @@ export const getServerSideProps: Types.GetServerSideProps = async (context) => { // fetch data concurrently const promises: [ - Promise, + Promise< + | { publicationVersion: Interfaces.PublicationVersion; versionRequestError: null } + | { publicationVersion: null; versionRequestError: { status: number; message: string } } + >, Promise, Promise, Promise, @@ -72,8 +75,14 @@ export const getServerSideProps: Types.GetServerSideProps = async (context) => { ] = [ api .get(`${Config.endpoints.publications}/${requestedId}/publication-versions/${versionId}`, token) - .then((res) => res.data) - .catch((error) => console.log(error)), + .then((res) => ({ publicationVersion: res.data, versionRequestError: null })) + .catch((error) => { + console.log(error); + const status = error.response.status; + const message = error.response.data.message; + + return { publicationVersion: null, versionRequestError: { status, message } }; + }), api .get(`${Config.endpoints.bookmarks}?type=PUBLICATION&entityId=${requestedId}`, token) .then((res) => res.data) @@ -93,31 +102,47 @@ export const getServerSideProps: Types.GetServerSideProps = async (context) => { ]; const [ - publicationVersion, + { publicationVersion, versionRequestError }, bookmarks = [], directLinks = { publication: null, linkedTo: [], linkedFrom: [] }, flags = [], topics = [] ] = await Promise.all(promises); - if (!publicationVersion) { + if (versionRequestError) { + const status = versionRequestError.status; + if (status === 404 || (token && status === 403)) { + return { + notFound: true + }; + } else if (status === 403) { + return { + redirect: { + destination: `${Config.urls.orcidLogin.path}&state=${encodeURIComponent(context.resolvedUrl)}`, + permanent: false + } + }; + } + } + + if (publicationVersion) { + return { + props: { + publicationVersion, + userToken: token || '', + bookmarkId: bookmarks.length ? bookmarks[0].id : null, + publicationId: publicationVersion.publication.id, + protectedPage: ['LOCKED', 'DRAFT'].includes(publicationVersion.currentStatus), + directLinks, + flags, + topics + } + }; + } else { return { notFound: true }; } - - return { - props: { - publicationVersion, - userToken: token || '', - bookmarkId: bookmarks.length ? bookmarks[0].id : null, - publicationId: publicationVersion.publication.id, - protectedPage: ['LOCKED', 'DRAFT'].includes(publicationVersion.currentStatus), - directLinks, - flags, - topics - } - }; }; type Props = {