fix(api): remove redirects from api

They should be handled either by nginx or by the client. Turned out a
lot of code, including the path migration, existed to support them.
Hence the large number of removals
This commit is contained in:
Oliver Eyton-Williams
2020-08-21 18:55:28 +02:00
committed by Mrugesh Mohapatra
parent 4a45b5ac1c
commit 1ad5f756e0
12 changed files with 3 additions and 234 deletions

View File

@ -44,8 +44,6 @@ seed/unpacked
server/rev-manifest.json server/rev-manifest.json
server/manifests/* server/manifests/*
!server/manifests/README.md !server/manifests/README.md
server/resources/pathMigration.json
webpack-bundle-stats.html webpack-bundle-stats.html
server/rev-manifest.json server/rev-manifest.json

View File

@ -1,3 +0,0 @@
const { createPathMigrationMap } = require('../seed/createPathMigrationMap');
createPathMigrationMap().then(() => console.info('path migration map created'));

View File

@ -5,7 +5,7 @@
* *
*/ */
import { Observable } from 'rx'; import { Observable } from 'rx';
import { isEmpty, pick, omit, find, uniqBy, last } from 'lodash'; import { isEmpty, pick, omit, find, uniqBy } from 'lodash';
import debug from 'debug'; import debug from 'debug';
import dedent from 'dedent'; import dedent from 'dedent';
import { ObjectID } from 'mongodb'; import { ObjectID } from 'mongodb';
@ -16,7 +16,6 @@ import { homeLocation } from '../../../config/env';
import { ifNoUserSend } from '../utils/middleware'; import { ifNoUserSend } from '../utils/middleware';
import { dasherize } from '../../../utils/slugs'; import { dasherize } from '../../../utils/slugs';
import _pathMigrations from '../resources/pathMigration.json';
import { fixCompletedChallengeItem } from '../../common/utils'; import { fixCompletedChallengeItem } from '../../common/utils';
import { getChallenges } from '../utils/get-curriculum'; import { getChallenges } from '../utils/get-curriculum';
@ -26,7 +25,6 @@ export default async function bootChallenge(app, done) {
const send200toNonUser = ifNoUserSend(true); const send200toNonUser = ifNoUserSend(true);
const api = app.loopback.Router(); const api = app.loopback.Router();
const router = app.loopback.Router(); const router = app.loopback.Router();
const redirectToLearn = createRedirectToLearn(_pathMigrations);
const challengeUrlResolver = await createChallengeUrlResolver( const challengeUrlResolver = await createChallengeUrlResolver(
await getChallenges() await getChallenges()
); );
@ -57,12 +55,6 @@ export default async function bootChallenge(app, done) {
router.get('/challenges/current-challenge', redirectToCurrentChallenge); router.get('/challenges/current-challenge', redirectToCurrentChallenge);
router.get('/challenges', redirectToLearn);
router.get('/challenges/*', redirectToLearn);
router.get('/map', redirectToLearn);
app.use(api); app.use(api);
app.use(router); app.use(router);
done(); done();
@ -357,18 +349,3 @@ export function createRedirectToCurrentChallenge(
return res.redirect(`${_homeLocation}${challengeUrl}`); return res.redirect(`${_homeLocation}${challengeUrl}`);
}; };
} }
export function createRedirectToLearn(
pathMigrations,
base = homeLocation,
learn = learnURL
) {
return function redirectToLearn(req, res) {
const maybeChallenge = last(req.path.split('/'));
if (maybeChallenge in pathMigrations) {
const redirectPath = pathMigrations[maybeChallenge];
return res.status(302).redirect(`${base}${redirectPath}`);
}
return res.status(302).redirect(learn);
};
}

View File

@ -9,8 +9,7 @@ import {
createChallengeUrlResolver, createChallengeUrlResolver,
createRedirectToCurrentChallenge, createRedirectToCurrentChallenge,
getFirstChallenge, getFirstChallenge,
isValidChallengeCompletion, isValidChallengeCompletion
createRedirectToLearn
} from '../boot/challenge'; } from '../boot/challenge';
import { import {
@ -21,8 +20,7 @@ import {
mockUser, mockUser,
mockGetFirstChallenge, mockGetFirstChallenge,
mockCompletedChallenge, mockCompletedChallenge,
mockCompletedChallenges, mockCompletedChallenges
mockPathMigrationMap
} from './fixtures'; } from './fixtures';
describe('boot/challenge', () => { describe('boot/challenge', () => {
@ -394,33 +392,4 @@ describe('boot/challenge', () => {
done(); done();
}); });
}); });
describe('redirectToLearn', () => {
const mockHome = 'https://example.com';
const mockLearn = 'https://example.com/learn';
const redirectToLearn = createRedirectToLearn(
mockPathMigrationMap,
mockHome,
mockLearn
);
it('redirects to learn by default', () => {
const req = mockReq({ path: '/challenges' });
const res = mockRes();
redirectToLearn(req, res);
expect(res.redirect.calledWith(mockLearn)).toBe(true);
});
it('maps to the correct redirect if the path matches a challenge', () => {
const req = mockReq({ path: '/challenges/challenge-two' });
const res = mockRes();
const expectedRedirect =
'https://example.com/learn/superblock/block/challenge-two';
redirectToLearn(req, res);
expect(res.redirect.calledWith(expectedRedirect)).toBe(true);
});
});
}); });

View File

@ -169,11 +169,6 @@ export const firstChallengeQuery = {
where: { challengeOrder: 0, superOrder: 1, order: 0 } where: { challengeOrder: 0, superOrder: 1, order: 0 }
}; };
export const mockPathMigrationMap = {
'challenge-one': '/learn/superblock/block/challenge-one',
'challenge-two': '/learn/superblock/block/challenge-two'
};
export const fullStackChallenges = [ export const fullStackChallenges = [
{ {
completedDate: 1585210952511, completedDate: 1585210952511,

View File

@ -1 +0,0 @@
# this file is here to add an empty dir to git

View File

@ -2,41 +2,10 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const debug = require('debug'); const debug = require('debug');
const log = debug('fcc:tools:ensure-env');
const env = require('../../../config/env'); const env = require('../../../config/env');
const { getChallengesForLang } = require('../../../curriculum/getChallenges');
const { createPathMigrationMap } = require('../seed/createPathMigrationMap');
const apiPath = path.resolve(__dirname, '../../../api-server');
const clientPath = path.resolve(__dirname, '../../../client'); const clientPath = path.resolve(__dirname, '../../../client');
const globalConfigPath = path.resolve(__dirname, '../../../config'); const globalConfigPath = path.resolve(__dirname, '../../../config');
const { FREECODECAMP_NODE_ENV } = process.env;
const { locale } = env;
const migrationMapPath = `${apiPath}/server/resources/pathMigration.json`;
fs.access(migrationMapPath, err => {
if (err && FREECODECAMP_NODE_ENV !== 'production') {
log('creating pathMigration');
return fs.writeFileSync(migrationMapPath, '{}');
}
if (FREECODECAMP_NODE_ENV === 'production') {
return getChallengesForLang(locale)
.then(createPathMigrationMap)
.then(map => {
fs.writeFileSync(migrationMapPath, JSON.stringify(map));
log('pathMigration has been written');
})
.catch(err => {
console.error(err);
// eslint-disable-next-line
process.exit(1);
});
}
log('pathMigration present');
return null;
});
fs.writeFileSync(`${clientPath}/config/env.json`, JSON.stringify(env)); fs.writeFileSync(`${clientPath}/config/env.json`, JSON.stringify(env));
fs.writeFileSync(`${globalConfigPath}/env.json`, JSON.stringify(env)); fs.writeFileSync(`${globalConfigPath}/env.json`, JSON.stringify(env));

View File

@ -1,30 +0,0 @@
const fs = require('fs');
const path = require('path');
const debug = require('debug');
const { getChallengesForLang } = require('../../../curriculum/getChallenges');
const { createPathMigrationMap } = require('../seed/createPathMigrationMap');
const log = debug('fcc:tools:ensure-env');
log.enabled = true;
const apiPath = path.resolve(__dirname, '../../api-server');
const migrationMapPath = `${apiPath}/server/resources/pathMigration.json`;
// The migrationMap is to try and resolve pre-learn challenge urls to
// current challenge urls
// defaulting to english as there were no other languages available
// that would require this mapping
getChallengesForLang('english')
.then(createPathMigrationMap)
.then(map => {
fs.writeFileSync(migrationMapPath, JSON.stringify(map));
log('pathMigration has been written');
})
.catch(err => {
console.error(err);
// eslint-disable-next-line
process.exit(1);
});

View File

@ -1,17 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`createPathMigrationMap output snapshot 1`] = `
Object {
"challenge-eight": "/learn/super-block-a/block-two/challenge-eight",
"challenge-eleven": "/learn/super-block-b/block-one/challenge-eleven",
"challenge-five": "/learn/super-block-a/block-two/challenge-five",
"challenge-four": "/learn/super-block-a/block-one/challenge-four",
"challenge-one": "/learn/super-block-a/block-one/challenge-one",
"challenge-seven": "/learn/super-block-a/block-two/challenge-seven",
"challenge-six": "/learn/super-block-a/block-two/challenge-six",
"challenge-ten": "/learn/super-block-b/block-one/challenge-ten",
"challenge-three": "/learn/super-block-a/block-one/challenge-three",
"challenge-twelve": "/learn/super-block-b/block-one/challenge-twelve",
"challenge-two": "/learn/super-block-a/block-one/challenge-two",
}
`;

View File

@ -1,27 +0,0 @@
const path = require('path');
const fs = require('fs');
require('dotenv').config({ path: path.resolve(__dirname, '../../../.env') });
const debug = require('debug');
const { getChallengesForLang } = require('../../../curriculum/getChallenges');
const { createPathMigrationMap } = require('./createPathMigrationMap');
const log = debug('fcc:tools:seedChallenges');
const { LOCALE: lang = 'english' } = process.env;
getChallengesForLang(lang).then(curriculum => {
log('generating path migration map');
const pathMap = createPathMigrationMap(curriculum);
const outputDir = path.resolve(
__dirname,
'../../../api-server/server/resources/pathMigration.json'
);
fs.writeFile(outputDir, JSON.stringify(pathMap), err => {
if (err) {
console.error('failed to save pathMigration');
console.error(err);
} else {
log('path migration map generated');
}
});
});

View File

@ -1,25 +0,0 @@
const { flatten } = require('lodash');
const { dasherize } = require('../../../utils/slugs');
function createPathMigrationMap(curriculum) {
return Object.keys(curriculum)
.map(key => curriculum[key].blocks)
.reduce((challenges, current) => {
const superChallenges = Object.keys(current).map(
key => current[key].challenges
);
return challenges.concat(flatten(superChallenges));
}, [])
.filter(({ isPrivate }) => !isPrivate)
.reduce((map, challenge) => {
const { title, block, superBlock } = challenge;
const dashedTitle = dasherize(title);
map[dashedTitle] = `/learn/${dasherize(superBlock)}/${dasherize(
block
)}/${dashedTitle}`;
return map;
}, {});
}
exports.createPathMigrationMap = createPathMigrationMap;

View File

@ -1,36 +0,0 @@
/* global describe expect */
const { isPlainObject } = require('lodash');
const { createPathMigrationMap } = require('./createPathMigrationMap');
const mockCurriculum = require('./__mocks__/curriculum.json');
describe('createPathMigrationMap', () => {
const pathMap = createPathMigrationMap(mockCurriculum);
it('is a function', () => {
expect(typeof createPathMigrationMap).toEqual('function');
});
it('returns an object', () => {
expect(isPlainObject(pathMap)).toBe(true);
});
it('maps a challenge title to the correct uri slug', () => {
expect.assertions(3);
const slugOne = '/learn/super-block-b/block-one/challenge-ten';
const slugTwo = '/learn/super-block-a/block-two/challenge-five';
const slugThree = '/learn/super-block-a/block-one/challenge-three';
expect(pathMap['challenge-ten']).toEqual(slugOne);
expect(pathMap['challenge-five']).toEqual(slugTwo);
expect(pathMap['challenge-three']).toEqual(slugThree);
});
it('does not add uri migrations for private challenges', () => {
expect(pathMap['challenge-nine']).toBeUndefined();
});
it('output snapshot', () => {
expect(createPathMigrationMap(mockCurriculum)).toMatchSnapshot();
});
});