Compare commits

...

1 Commits

Author SHA1 Message Date
Michael Terry
4d67042660 fix: handle new 403 "redirect" responses from backend
To make it easier to redirect the user to an another page or an
access denied error page, this PR deprecates the old custom 401 &
404 error handling, replacing them both with a generic 403 error
code that contains a URL to redirect the user to.

Before this change, we weren't handling all the error cases, and
when we didn't, we ended up showing a broken page to the user.
2021-07-20 13:30:27 -04:00
2 changed files with 44 additions and 1 deletions

View File

@@ -182,6 +182,26 @@ export function normalizeOutlineBlocks(courseId, blocks) {
return models;
}
function processTabDataErrorRedirect(error) {
const { httpErrorResponseData, httpErrorStatus } = error && error.customAttributes;
if (httpErrorStatus === 403) {
// Currently, only 403 errors contain redirect content
try {
const { redirect } = JSON.parse(httpErrorResponseData);
if (redirect) {
global.location.replace(redirect);
return true;
}
} catch (exc) {
// ignore any json parse errors, might be an actual 403 without redirect json content
}
}
// Did not do any redirecting
return false;
}
export async function getCourseHomeCourseMetadata(courseId) {
let url = `${getConfig().LMS_BASE_URL}/api/course_home/v1/course_metadata/${courseId}`;
url = appendBrowserTimezoneToUrl(url);
@@ -202,11 +222,18 @@ export async function getDatesTabData(courseId) {
} catch (error) {
const { httpErrorStatus } = error && error.customAttributes;
if (httpErrorStatus === 404) {
// TODO: remove this - not needed once the backend uses 403s for redirects
global.location.replace(`${getConfig().LMS_BASE_URL}/courses/${courseId}/dates`);
return null;
}
// 401 can be returned for unauthenticated users or users who are not enrolled
if (httpErrorStatus === 401) {
// TODO: remove this - not needed once the backend uses 403s for redirects
global.location.replace(`${getConfig().BASE_URL}/course/${courseId}/home`);
return null;
}
if (processTabDataErrorRedirect(error)) {
return null; // keeps loading screen active
}
throw error;
}
@@ -249,11 +276,18 @@ export async function getProgressTabData(courseId, targetUserId) {
} catch (error) {
const { httpErrorStatus } = error && error.customAttributes;
if (httpErrorStatus === 404) {
// TODO: remove this - not needed once the backend uses 403s for redirects
global.location.replace(`${getConfig().LMS_BASE_URL}/courses/${courseId}/progress`);
return null;
}
// 401 can be returned for unauthenticated users or users who are not enrolled
if (httpErrorStatus === 401) {
// TODO: remove this - not needed once the backend uses 403s for redirects
global.location.replace(`${getConfig().BASE_URL}/course/${courseId}/home`);
return null;
}
if (processTabDataErrorRedirect(error)) {
return null; // keeps loading screen active
}
throw error;
}
@@ -303,8 +337,12 @@ export async function getOutlineTabData(courseId) {
} catch (error) {
const { httpErrorStatus } = error && error.customAttributes;
if (httpErrorStatus === 404) {
// TODO: remove this - not needed once the backend uses 403s for redirects
global.location.replace(`${getConfig().LMS_BASE_URL}/courses/${courseId}/course/`);
return {};
return null;
}
if (processTabDataErrorRedirect(error)) {
return null; // keeps loading screen active
}
throw error;
}

View File

@@ -49,6 +49,11 @@ export function fetchTab(courseId, tab, getTabData, targetUserId) {
logError(courseHomeCourseMetadataResult.reason);
}
if (fetchedTabData && tabDataResult.value === null) {
// null tab data indicates that we have redirected elsewhere - just exit and don't visibly stop loading
return;
}
if (fetchedTabData) {
dispatch(addModel({
modelType: tab,