Skip to content

Commit

Permalink
bootstrap application, added routers and some tests
Browse files Browse the repository at this point in the history
  • Loading branch information
fcaps authored and Brutus5000 committed Nov 22, 2023
1 parent 85474c5 commit 0a42c9e
Show file tree
Hide file tree
Showing 30 changed files with 562 additions and 219 deletions.
198 changes: 7 additions & 191 deletions express.js
Original file line number Diff line number Diff line change
@@ -1,193 +1,9 @@
const appConfig = require('./config/app')
const express = require('express');
const showdown = require('showdown');
const passport = require('passport');
const session = require('express-session');
const FileStore = require('session-file-store')(session);
const bodyParser = require('body-parser');
const flash = require('connect-flash');
const setupCronJobs = require('./scripts/cron-jobs');
const middleware = require('./routes/middleware');
const app = express();
const newsRouter = require('./routes/views/news');
const staticMarkdownRouter = require('./routes/views/staticMarkdownRouter');
const leaderboardRouter = require('./routes/views/leaderboardRouter');
const authRouter = require('./routes/views/auth');
const dataRouter = require('./routes/views/dataRouter');
const fafApp = require('./fafApp')
const express = require('express')
const app = express()

app.locals.clanInvitations = {};
fafApp.setup(app)
fafApp.loadRouters(app)
fafApp.setupCronJobs()

//Execute Middleware
app.use(middleware.injectServices);
app.use(middleware.initLocals);

//Set static public directory path
app.use(express.static('public', {
immutable: true,
maxAge: 4 * 60 * 60 * 1000 // 4 hours
}));

app.use(express.json());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));

app.use(session({
resave: false,
saveUninitialized: true,
secret: appConfig.session.key,
store: new FileStore({
retries: 0,
ttl: appConfig.session.tokenLifespan,
secret: appConfig.session.key
})
}));

app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(middleware.username);

//Initialize values for default configs
app.set('views', 'templates/views');
app.set('view engine', 'pug');
app.set('port', appConfig.expressPort);

app.use(function(req, res, next){
res.locals.message = req.flash();
next();
});

let fullUrl = '/';

function loggedIn(req, res, next) {

fullUrl = `${req.protocol}://${req.get('host')}${req.originalUrl}`;

if (req.isAuthenticated()) {
res.locals.username = req.user.data.attributes.userName;
next();
} else {
res.redirect('/login');
}
}

app.use('/', authRouter)
app.use('/', staticMarkdownRouter)
app.use('/news', newsRouter)
app.use('/leaderboards', leaderboardRouter)
app.use('/data', dataRouter)

// --- UNPROTECTED ROUTES ---
const appGetRouteArray = [
// This first '' is the home/index page
'', 'newshub', 'campaign-missions', 'scfa-vs-faf', 'donation', 'tutorials-guides', 'ai', 'patchnotes', 'faf-teams', 'contribution', 'content-creators', 'tournaments', 'training', 'play', 'clans',];

//Renders every page written above
appGetRouteArray.forEach(page => app.get(`/${page}`, (req, res) => {
// disabled due https://github.com/FAForever/website/issues/445
if (page === 'clans') {
return res.status(503).render('errors/503-known-issue')
}
res.render(page);
}));

/*
// List of route name changes
reset > requestPasswordReset
confirmReset > confirmPasswordReset
change > changePassword, changeUsername, changeEmail
*/

// Account routes
// These routes are protected by the 'loggedIn' function (which verifies if user is serialized/deserialized or logged in [same thing]).
const accountRoutePath = './routes/views/account';
const protectedAccountRoutes = [
'linkGog', 'report', 'changePassword', 'changeEmail', 'changeUsername',];

protectedAccountRoutes.forEach(page => app.post(`/account/${page}`, loggedIn, require(`${accountRoutePath}/post/${page}`)));

protectedAccountRoutes.forEach(page => app.get(`/account/${page}`, loggedIn, require(`${accountRoutePath}/get/${page}`)));


//Password reset routes
const passwordResetRoutes = ['requestPasswordReset', 'confirmPasswordReset'];

passwordResetRoutes.forEach(page => app.post(`/account/${page}`, require(`${accountRoutePath}/post/${page}`)));
passwordResetRoutes.forEach(page => app.get(`/account/${page}`, require(`${accountRoutePath}/get/${page}`)));

app.get('/account/password/confirmReset', require(`${accountRoutePath}/get/confirmPasswordReset`));
app.post('/account/password/confirmReset', require(`${accountRoutePath}/post/confirmPasswordReset`));

//legacy password reset path for backwards compatibility
app.get('/account/password/reset', require(`${accountRoutePath}/get/requestPasswordReset`));
app.post('/account/password/reset', require(`${accountRoutePath}/post/requestPasswordReset`));


// --- C L A N S ---
const routes = './routes/views/';

const clansRoutesGet = [
'create', 'manage', 'accept_invite',];
// disabled due https://github.com/FAForever/website/issues/445
// clansRoutesGet.forEach(page => app.get(`/clans/${page}`, loggedIn, require(`${routes}clans/get/${page}`)));
clansRoutesGet.forEach(page => app.get(`/clans/${page}`, loggedIn, (req, res) => res.status(503).render('errors/503-known-issue')));

const clansRoutesPost = [
'create', 'destroy', 'invite', 'kick', 'transfer', 'update', 'leave', 'join',];
// disabled due https://github.com/FAForever/website/issues/445
// clansRoutesPost.forEach(page => app.post(`/clans/${page}`, loggedIn, require(`${routes}clans/post/${page}`)));
clansRoutesPost.forEach(page => app.post(`/clans/${page}`, loggedIn, (req, res) => res.status(503).render('errors/503-known-issue')));


// disabled due https://github.com/FAForever/website/issues/445
//When searching for a specific clan
// app.get('/clans/*', (req, res) => {
// res.render(`clans/seeClan`);
// });
app.get('/clans/*', (req, res) => res.status(503).render('errors/503-known-issue'));


// ---ODD BALLS---
// Routes that might not be able to be added into the loops due to their nature in naming
/* Removed
client.js (was made its own code below)
lobby_api (not in use in the new website)
*/
// Protected

app.get('/account/link', loggedIn, require(routes + 'account/get/linkSteam'));
//app.get('/account/linkSteam', loggedIn, require(routes + 'account/get/linkSteam'));
app.get('/account/connect', loggedIn, require(routes + 'account/get/connectSteam'));
//app.get('/account/connectSteam', loggedIn, require(routes + 'account/get/connectSteam'));
app.get('/account/resync', loggedIn, require(routes + 'account/get/resync'));
// Not Protected
app.get('/account/create', require(routes + 'account/get/createAccount'));
app.get('/account_activated', require(routes + 'account/get/register'));
app.get('/account/register', require(routes + 'account/get/register'));
app.post('/account/register', require(routes + 'account/post/register'));

app.get('/account/activate', require(routes + 'account/get/activate'));
app.post('/account/activate', require(routes + 'account/post/activate'));

app.get('/account/checkUsername', require('./routes/views/checkUsername'));
app.get('/password_resetted', require(routes + 'account/get/requestPasswordReset'));
app.get('/report_submitted', require(routes + 'account/get/report'));

setupCronJobs()

//404 Error Handlers
app.use(function (req, res) {
res.status(404).render('errors/404');
});
app.use(function (err, req, res, next) {
console.error('[error] Incoming request to"', req.originalUrl, '"failed with error "', err.toString(), '"')
if (res.headersSent) {
return next(err);
}

res.status(500).render('errors/500');
});

app.listen(appConfig.expressPort, () => {
console.log(`Express listening on port ${appConfig.expressPort}`);
});
fafApp.startServer(app)
94 changes: 94 additions & 0 deletions fafApp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
const appConfig = require("./config/app")
const express = require('express')
const bodyParser = require('body-parser')
const session = require('express-session')
const FileStore = require('session-file-store')(session)
const passport = require('passport')
const flash = require('connect-flash')
const middleware = require('./routes/middleware')
const defaultRouter = require("./routes/views/defaultRouter")
const authRouter = require("./routes/views/auth")
const staticMarkdownRouter = require("./routes/views/staticMarkdownRouter")
const newsRouter = require("./routes/views/news")
const leaderboardRouter = require("./routes/views/leaderboardRouter")
const clanRouter = require("./routes/views/clanRouter")
const accountRouter = require("./routes/views/accountRouter")
const dataRouter = require('./routes/views/dataRouter');
const setupCronJobs = require("./scripts/cron-jobs")

const copyFlashHandler = (req, res, next) => {
res.locals.message = req.flash();
next();
}
const notFoundHandler = (req, res) => {
res.status(404).render('errors/404');
}

const errorHandler = (err, req, res, next) => {
console.error('[error] Incoming request to"', req.originalUrl, '"failed with error "', err.toString(), '"')
if (res.headersSent) {
return next(err);
}

res.status(500).render('errors/500');
}

module.exports.setupCronJobs = () => {
setupCronJobs()
}

module.exports.startServer = (app) => {
app.listen(appConfig.expressPort, () => {
console.log(`Express listening on port ${appConfig.expressPort}`);
});
}

module.exports.loadRouters = (app) => {
app.use('/', defaultRouter)
app.use('/', authRouter)
app.use('/', staticMarkdownRouter)
app.use('/news', newsRouter)
app.use('/leaderboards', leaderboardRouter)
app.use('/clans', clanRouter)
app.use('/account', accountRouter)
app.use('/data', dataRouter)

app.use(notFoundHandler)
app.use(errorHandler)
}

module.exports.setup = (app) => {
app.locals.clanInvitations = {}

app.set('views', 'templates/views')
app.set('view engine', 'pug')
app.set('port', appConfig.expressPort)

app.use(middleware.injectServices)
app.use(middleware.initLocals)

app.use(express.static('public', {
immutable: true,
maxAge: 4 * 60 * 60 * 1000 // 4 hours
}))

app.use(express.json())
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: false}))

app.use(session({
resave: false,
saveUninitialized: true,
secret: appConfig.session.key,
store: new FileStore({
retries: 0,
ttl: appConfig.session.tokenLifespan,
secret: appConfig.session.key
})
}))
app.use(passport.initialize())
app.use(passport.session())
app.use(flash())
app.use(middleware.username)
app.use(copyFlashHandler)
}
43 changes: 43 additions & 0 deletions routes/views/accountRouter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const express = require('express')
const router = express.Router();
const middlewares = require('../middleware')


router.get('/linkGog', middlewares.isAuthenticated(), require('./account/get/linkGog'))
router.post('/linkGog', middlewares.isAuthenticated(), require('./account/post/linkGog'))

router.get('/report', middlewares.isAuthenticated(), require('./account/get/report'))
router.post('/report', middlewares.isAuthenticated(), require('./account/post/report'))

router.get('/changePassword', middlewares.isAuthenticated(), require('./account/get/changePassword'))
router.post('/changePassword', middlewares.isAuthenticated(), require('./account/post/changePassword'))

router.get('/changeEmail', middlewares.isAuthenticated(), require('./account/get/changeEmail'))
router.post('/changeEmail', middlewares.isAuthenticated(), require('./account/post/changeEmail'))

router.get('/changeUsername', middlewares.isAuthenticated(), require('./account/get/changeUsername'))
router.post('/changeUsername', middlewares.isAuthenticated(), require('./account/post/changeUsername'))

router.get('/password/confirmReset', require('./account/get/confirmPasswordReset'))
router.post('/password/confirmReset', require('./account/post/confirmPasswordReset'))

router.get('/requestPasswordReset', require('./account/get/requestPasswordReset'))
router.post('/requestPasswordReset', require('./account/post/requestPasswordReset'))

//still used in other applications (user-service, game-client etc.)
router.get('/password/reset', (req, res) => res.redirect('/account/requestPasswordReset'))


router.get('/register', require('./account/get/register'))
router.post('/register', require('./account/post/register'))

router.get('/activate', require('./account/get/activate'))
router.post('/activate', require('./account/post/activate'))

router.get('/checkUsername', require('./checkUsername'))
router.get('/resync', middlewares.isAuthenticated(), require('./account/get/resync'))
router.get('/create', require('./account/get/createAccount'))
router.get('/link', middlewares.isAuthenticated(), require('./account/get/linkSteam'))
router.get('/connect', middlewares.isAuthenticated(), require('./account/get/connectSteam'))

module.exports = router
7 changes: 7 additions & 0 deletions routes/views/clanRouter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const express = require('express');
const router = express.Router();

// This will be replaced soon, therefor I did not spend time on it
router.get('*', (req, res) => res.status(503).render('errors/503-known-issue'));

module.exports = router
25 changes: 25 additions & 0 deletions routes/views/defaultRouter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const express = require('express');
const router = express.Router();

router.get('/', (req, res) => res.render('index'))
router.get('/newshub', (req, res) => res.render('newshub'))
router.get('/campaign-missions', (req, res) => res.render('campaign-missions'))
router.get('/scfa-vs-faf', (req, res) => res.render('scfa-vs-faf'))
router.get('/ai', (req, res) => res.render('ai'))
router.get('/donation', (req, res) => res.render('donation'))
router.get('/tutorials-guides', (req, res) => res.render('tutorials-guides'))
router.get('/faf-teams', (req, res) => res.render('faf-teams'))
router.get('/contribution', (reqd, res) => res.render('contribution'))
router.get('/content-creators', (reqd, res) => res.render('content-creators'))
router.get('/play', (reqd, res) => res.render('play'))

// https://github.com/search?q=org%3AFAForever+account_activated&type=code
router.get('/account_activated', (req, res) => res.redirect('/account/register'))

// see: https://github.com/search?q=org%3AFAForever%20password_resetted&type=code
router.get('/password_resetted', (req, res) => res.redirect('/account/requestPasswordReset'))

// this is prob. outdated, but don't know
router.get('/report_submitted', require('./account/get/report'))

module.exports = router
2 changes: 1 addition & 1 deletion routes/views/leaderboardRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ router.get('/:leaderboard.json', middlewares.isAuthenticated(null, true), async
const leaderboardId = getLeaderboardId(req.params.leaderboard ?? null);

if (leaderboardId === null) {
return res.status(404).json({error: 'Leaderboard "' + req.params.leaderboard + '"does not exist'})
return res.status(404).json({error: 'Leaderboard "' + req.params.leaderboard + '" does not exist'})
}

const token = req.user.data.attributes.token
Expand Down
2 changes: 1 addition & 1 deletion templates/views/account/confirmPasswordReset.pug
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ block content

.row
.col-md-offset-3.col-md-6
form(method='post',action="/account/confirmPasswordReset?username="+username+"&token="+token,data-toggle="validator")
form(method='post',action="/account/password/confirmReset?username="+username+"&token="+token,data-toggle="validator")
+confirm-password
.form-actions
button(type='submit').btn.btn-default.btn-lg.btn-outro.btn-danger Reset
Expand Down
Loading

0 comments on commit 0a42c9e

Please sign in to comment.