Skip to content

Commit

Permalink
init m2m client
Browse files Browse the repository at this point in the history
  • Loading branch information
fcaps committed Nov 29, 2023
1 parent 29b71cb commit 1564de4
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 37 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ API_URL=https://api.test.faforever.com
OAUTH_URL=https://hydra.test.faforever.com
WP_URL=https://direct.faforever.com
CALLBACK=auth
OAUTH_M2M_CLIENT_ID=faf-website-public
OAUTH_M2M_CLIENT_SECRET=banana
OAUTH_CLIENT_ID=faf-website
OAUTH_CLIENT_SECRET=banana
SESSION_SECRET_KEY=banana
Expand Down
3 changes: 2 additions & 1 deletion .env.faf-stack
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ OAUTH_PUBLIC_URL=http://localhost:4444

# unsing the "xyz" wordpress because the faf-local-stack is just an empty instance without any news etc.
WP_URL=https://direct.faforever.xyz

OAUTH_M2M_CLIENT_ID=faf-website-public
OAUTH_M2M_CLIENT_SECRET=banana
OAUTH_CLIENT_ID=faf-website
OAUTH_CLIENT_SECRET=banana
SESSION_SECRET_KEY=banana
Expand Down
5 changes: 5 additions & 0 deletions config/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ const appConfig = {
publicUrl: process.env.OAUTH_PUBLIC_URL || oauthUrl,
callback: process.env.CALLBACK || 'callback',
},
m2mOauth: {
clientId: process.env.OAUTH_M2M_CLIENT_ID || 'faf-website-public',
clientSecret: process.env.OAUTH_M2M_CLIENT_SECRET || 'banana',
url: oauthUrl,
},
apiUrl: process.env.API_URL || 'https://api.faforever.com',
wordpressUrl: process.env.WP_URL || 'https://direct.faforever.com',
extractorInterval: process.env.EXTRACTOR_INTERVAL || 5,
Expand Down
6 changes: 6 additions & 0 deletions lib/JavaApiM2MClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const { JavaApiM2MClientFactory } = require("./JavaApiM2MClientFactory");
const appConfig = require("../config/app");

const client = JavaApiM2MClientFactory(appConfig.m2mOauth.clientId, appConfig.m2mOauth.clientSecret, appConfig.m2mOauth.url, appConfig.apiUrl)

module.exports.JavaApiM2MClient = client
51 changes: 51 additions & 0 deletions lib/JavaApiM2MClientFactory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const {ClientCredentials} = require("simple-oauth2");
const { Axios } = require("axios");
const { AuthFailed } = require("./ApiErrors");

const getToken = async function(clientId, clientSecret, host, scope) {
const tokenClient = new ClientCredentials({
client: {
id: clientId,
secret: clientSecret,

},
auth: {
tokenHost: host,
tokenPath: '/oauth2/token',
revokePath: '/oauth2/revoke'
},
options: {
authorizationMethod: 'body'
}
})

try {
return tokenClient.getToken({
scope: scope ?? '',
})
} catch (error) {
throw new AuthFailed(error.toString())
}
}

module.exports.JavaApiM2MClientFactory = async function(clientId, clientSecret, host, javaApiBaseURL) {
let passport = await getToken(clientId, clientSecret, host, '')

const client = new Axios({
baseURL: javaApiBaseURL
})

client.interceptors.request.use(config => {
if (passport.expired()) {
passport = passport.refresh()
}

config.headers = {
Authorization: `Bearer ${passport.token.access_token}`
}

return config;
});

return client
}
4 changes: 2 additions & 2 deletions lib/LeaderboardService.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ class LeaderboardService {
this.leaderboardRepository = leaderboardRepository
}

async getLeaderboard(id) {
async getLeaderboard(id, ignoreCache = false) {

if (typeof (id) !== 'number') {
throw new Error('LeaderboardService:getLeaderboard id must be a number')
}

const cacheKey = 'leaderboard-' + id

if (this.cacheService.has(cacheKey)) {
if (this.cacheService.has(cacheKey) && ignoreCache === false) {
return this.cacheService.get(cacheKey)
}

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"request": "2.88.2",
"session-file-store": "^1.5.0",
"showdown": "^2.1.0",
"simple-oauth2": "^5.0.0",
"supertest-session": "^5.0.1",
"url-slug": "^4.0.1"
},
Expand Down
32 changes: 19 additions & 13 deletions routes/middleware.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const WordpressServiceFactory = require("../lib/WordpressServiceFactory");
const {JavaApiClientFactory} = require('../lib/JavaApiClientFactory')
const {JavaApiM2MClient} = require('../lib/JavaApiM2MClient')
const LeaderboardService = require('../lib/LeaderboardService')
const LeaderboardRepository = require('../lib/LeaderboardRepository')
const cacheService = require('../lib/CacheService')
Expand All @@ -9,7 +10,7 @@ const fs = require('fs');
const webpackManifestJS = JSON.parse(fs.readFileSync('dist/js/manifest.json', 'utf8'));
const LoggedInUserService = require('../lib/LoggedInUserService')
const UserRepository = require('../lib/UserRepository');


exports.initLocals = function(req, res, next) {
let locals = res.locals;
Expand Down Expand Up @@ -59,19 +60,24 @@ exports.isAuthenticated = (redirectUrlAfterLogin = null, isApiRequest = false) =
}
}

exports.injectServices = (req, res, next) => {
req.services = {}
req.services.wordpressService = wordpressService
exports.injectServices = async (req, res, next) => {
try {
req.services = {}
req.services.wordpressService = wordpressService
req.services.javaApiM2MClient = await JavaApiM2MClient
req.services.leaderboardService = new LeaderboardService(cacheService, new LeaderboardRepository(req.services.javaApiM2MClient))

if (req.isAuthenticated()) {
try {
req.services.javaApiClient = JavaApiClientFactory(appConfig.apiUrl, req.user.oAuthPassport)
req.services.userService = new LoggedInUserService(new UserRepository(req.services.javaApiClient), req)
req.services.leaderboardService = new LeaderboardService(cacheService, new LeaderboardRepository(req.services.javaApiClient))
} catch (e) {
req.logout(() => next(e))
if (req.isAuthenticated()) {
try {
req.services.javaApiClient = JavaApiClientFactory(appConfig.apiUrl, req.user.oAuthPassport)
req.services.userService = new LoggedInUserService(new UserRepository(req.services.javaApiClient), req)
} catch (e) {
req.logout(() => next(e))
}
}
}

next()
next()
} catch (e) {
next(e)
}
}
14 changes: 2 additions & 12 deletions routes/views/leaderboardRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ const getLeaderboardId = (leaderboardName) => {
return null
}

router.get('/', middlewares.isAuthenticated(), (req, res) => {
router.get('/', (req, res) => {
return res.render('leaderboards')
})

router.get('/:leaderboard.json', middlewares.isAuthenticated(null, true), async (req, res) => {
router.get('/:leaderboard.json', async (req, res) => {
try {
const leaderboardId = getLeaderboardId(req.params.leaderboard ?? null);

Expand All @@ -38,16 +38,6 @@ router.get('/:leaderboard.json', middlewares.isAuthenticated(null, true), async
return res.status(503).json({error: 'timeout reached'})
}

if (e instanceof AuthFailed) {
req.logout(function(err) {
if (err) {
throw err
}
})

return res.status(400).json({error: 'authentication failed, reload site'})
}

console.error('[error] leaderboardRouter::get:leaderboard.json failed with "' + e.toString() + '"')

if (!res.headersSent) {
Expand Down
35 changes: 26 additions & 9 deletions scripts/cron-jobs.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,44 @@
const appConfig = require("../config/app")
const WordpressServiceFactory = require("../lib/WordpressServiceFactory");
const Scheduler = require("../lib/Scheduler");
const LeaderboardService = require("../lib/LeaderboardService");
const cacheService = require("../lib/CacheService");
const LeaderboardRepository = require("../lib/LeaderboardRepository");
const {JavaApiM2MClient} = require('../lib/JavaApiM2MClient')

const warmupWordpressCache = async () => {
const successHandler = (name) => {
console.info(name, 'cache generated')
}
const errorHandler = (e, name) => {
console.error(name, e.toString(), 'cache failed')
}

const warmupWordpressCache = () => {
const wordpressService = WordpressServiceFactory(appConfig.wordpressUrl)

const successHandler = (name) => {
console.info(name, 'cache generated')
}
const errorHandler = (e, name) => {
console.error(name, e.toString(), 'cache failed')
}

wordpressService.getNews(true).then(() => successHandler('getNews')).catch((e) => errorHandler(e, 'getNews'))
wordpressService.getNewshub(true).then(() => successHandler('getNewshub')).catch((e) => errorHandler(e, 'getNewshub'))
wordpressService.getContentCreators(true).then(() => successHandler('getContentCreators')).catch((e) => errorHandler(e, 'getContentCreators'))
wordpressService.getTournamentNews(true).then(() => successHandler('getTournamentNews')).catch((e) => errorHandler(e, 'getTournamentNews'))
wordpressService.getFafTeams(true).then(() => successHandler('getFafTeams')).catch((e) => errorHandler(e, 'getFafTeams'))
}

const warmupLeaderboard = async () => {
const leaderboardService = new LeaderboardService(cacheService, new LeaderboardRepository(await JavaApiM2MClient))

await leaderboardService.getLeaderboard(1, true).then(() => successHandler('getLeaderboard(global)')).catch((e) => errorHandler(e, 'getLeaderboard(global)'))
await leaderboardService.getLeaderboard(2, true).then(() => successHandler('getLeaderboard(1v1)')).catch((e) => errorHandler(e, 'getLeaderboard(1v1)'))
await leaderboardService.getLeaderboard(3, true).then(() => successHandler('getLeaderboard(2v2)')).catch((e) => errorHandler(e, 'getLeaderboard(2v2)'))
await leaderboardService.getLeaderboard(4, true).then(() => successHandler('getLeaderboard(4v4)')).catch((e) => errorHandler(e, 'getLeaderboard(4v4)'))
}

module.exports = async () => {
await warmupWordpressCache()
warmupWordpressCache()
await warmupLeaderboard()

const wordpressScheduler = new Scheduler('createWordpressCaches', warmupWordpressCache, 60 * 59 * 1000)
wordpressScheduler.start()

const leaderboardScheduler = new Scheduler('createLeaderboardCaches', warmupLeaderboard, 60 * 59 * 1000)
leaderboardScheduler.start()
}
81 changes: 81 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,49 @@
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.54.0.tgz#4fab9a2ff7860082c304f750e94acd644cf984cf"
integrity sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==

"@hapi/boom@^10.0.1":
version "10.0.1"
resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-10.0.1.tgz#ebb14688275ae150aa6af788dbe482e6a6062685"
integrity sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==
dependencies:
"@hapi/hoek" "^11.0.2"

"@hapi/bourne@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-3.0.0.tgz#f11fdf7dda62fe8e336fa7c6642d9041f30356d7"
integrity sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==

"@hapi/hoek@^10.0.1":
version "10.0.1"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-10.0.1.tgz#ee9da297fabc557e1c040a0f44ee89c266ccc306"
integrity sha512-CvlW7jmOhWzuqOqiJQ3rQVLMcREh0eel4IBnxDx2FAcK8g7qoJRQK4L1CPBASoCY6y8e6zuCy3f2g+HWdkzcMw==

"@hapi/hoek@^11.0.2":
version "11.0.2"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-11.0.2.tgz#cb3ea547daac7de5c9cf1d960c3f35c34f065427"
integrity sha512-aKmlCO57XFZ26wso4rJsW4oTUnrgTFw2jh3io7CAtO9w4UltBNwRXvXIVzzyfkaaLRo3nluP/19msA8vDUUuKw==

"@hapi/hoek@^9.0.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==

"@hapi/topo@^5.0.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
dependencies:
"@hapi/hoek" "^9.0.0"

"@hapi/wreck@^18.0.0":
version "18.0.1"
resolved "https://registry.yarnpkg.com/@hapi/wreck/-/wreck-18.0.1.tgz#6df04532be25fd128c5244e72ccc21438cf8bb65"
integrity sha512-OLHER70+rZxvDl75xq3xXOfd3e8XIvz8fWY0dqg92UvhZ29zo24vQgfqgHSYhB5ZiuFpSLeriOisAlxAo/1jWg==
dependencies:
"@hapi/boom" "^10.0.1"
"@hapi/bourne" "^3.0.0"
"@hapi/hoek" "^11.0.2"

"@humanwhocodes/config-array@^0.11.13":
version "0.11.13"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297"
Expand Down Expand Up @@ -862,6 +905,23 @@
resolved "https://registry.yarnpkg.com/@servie/events/-/events-1.0.0.tgz#8258684b52d418ab7b86533e861186638ecc5dc1"
integrity sha512-sBSO19KzdrJCM3gdx6eIxV8M9Gxfgg6iDQmH5TIAGaUu+X9VDdsINXJOnoiZ1Kx3TrHdH4bt5UVglkjsEGBcvw==

"@sideway/address@^4.1.3":
version "4.1.4"
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0"
integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==
dependencies:
"@hapi/hoek" "^9.0.0"

"@sideway/formula@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==

"@sideway/pinpoint@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==

"@sinclair/typebox@^0.27.8":
version "0.27.8"
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e"
Expand Down Expand Up @@ -5199,6 +5259,17 @@ jit-grunt@0.10.0:
resolved "https://registry.yarnpkg.com/jit-grunt/-/jit-grunt-0.10.0.tgz#008c3a7fe1e96bd0d84e260ea1fa1783457f79c2"
integrity sha512-eT/f4c9wgZ3buXB7X1JY1w6uNtAV0bhrbOGf/mFmBb0CDNLUETJ/VRoydayWOI54tOoam0cz9RooVCn3QY1WoA==

joi@^17.6.4:
version "17.11.0"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.11.0.tgz#aa9da753578ec7720e6f0ca2c7046996ed04fc1a"
integrity sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==
dependencies:
"@hapi/hoek" "^9.0.0"
"@hapi/topo" "^5.0.0"
"@sideway/address" "^4.1.3"
"@sideway/formula" "^3.0.1"
"@sideway/pinpoint" "^2.0.0"

jquery@^3.7.1:
version "3.7.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de"
Expand Down Expand Up @@ -7501,6 +7572,16 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==

simple-oauth2@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/simple-oauth2/-/simple-oauth2-5.0.0.tgz#3b7d85700944b26f8f5451c017426292f330460c"
integrity sha512-8291lo/z5ZdpmiOFzOs1kF3cxn22bMj5FFH+DNUppLJrpoIlM1QnFiE7KpshHu3J3i21TVcx4yW+gXYjdCKDLQ==
dependencies:
"@hapi/hoek" "^10.0.1"
"@hapi/wreck" "^18.0.0"
debug "^4.3.4"
joi "^17.6.4"

sisteransi@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
Expand Down

0 comments on commit 1564de4

Please sign in to comment.