mirror of
https://github.com/vkaelin/LeagueStats.git
synced 2026-03-25 12:57:28 +00:00
Use Adonis instead of Express for the API
This commit is contained in:
parent
d611a7647d
commit
9cc044ec13
37 changed files with 4278 additions and 2915 deletions
|
|
@ -4,7 +4,7 @@ export const axios = axiosHttp
|
||||||
|
|
||||||
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
|
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
|
||||||
axios.defaults.headers.common['Content-Type'] = 'application/json'
|
axios.defaults.headers.common['Content-Type'] = 'application/json'
|
||||||
axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? 'http://localhost:3333/' : 'https://api.valentinkaelin.ch/'
|
axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? 'http://localhost:5000/' : 'https://api.valentinkaelin.ch/'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install (Vue) {
|
install (Vue) {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"presets": [
|
|
||||||
"@babel/preset-env"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"@babel/plugin-transform-runtime"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
13
server/.editorconfig
Normal file
13
server/.editorconfig
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
21
server/.env.example
Normal file
21
server/.env.example
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
HOST=127.0.0.1
|
||||||
|
PORT=5000
|
||||||
|
NODE_ENV=development
|
||||||
|
|
||||||
|
APP_NAME=LeagueStats
|
||||||
|
APP_URL=http://${HOST}:${PORT}
|
||||||
|
|
||||||
|
CACHE_VIEWS=false
|
||||||
|
|
||||||
|
APP_KEY=
|
||||||
|
|
||||||
|
DB_CONNECTION=mongodb
|
||||||
|
DB_HOST=127.0.0.1
|
||||||
|
DB_PORT=27017
|
||||||
|
DB_USER=root
|
||||||
|
DB_PASSWORD=
|
||||||
|
DB_DATABASE=leaguestats
|
||||||
|
|
||||||
|
HASH_DRIVER=bcrypt
|
||||||
|
|
||||||
|
API_KEY=RGAPI-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
13
server/.gitignore
vendored
13
server/.gitignore
vendored
|
|
@ -1,4 +1,11 @@
|
||||||
/build
|
# Node modules
|
||||||
/node_modules
|
node_modules
|
||||||
/DDragon
|
|
||||||
|
# Adonis directory for storing tmp files
|
||||||
|
tmp
|
||||||
|
|
||||||
|
# Environment variables, never commit this file
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
# The development sqlite file
|
||||||
|
database/development.sqlite
|
||||||
|
|
|
||||||
28
server/README.md
Normal file
28
server/README.md
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Adonis API application
|
||||||
|
|
||||||
|
This is the boilerplate for creating an API server in AdonisJs, it comes pre-configured with.
|
||||||
|
|
||||||
|
1. Bodyparser
|
||||||
|
2. Authentication
|
||||||
|
3. CORS
|
||||||
|
4. Lucid ORM
|
||||||
|
5. Migrations and seeds
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Use the adonis command to install the blueprint
|
||||||
|
|
||||||
|
```bash
|
||||||
|
adonis new yardstick --api-only
|
||||||
|
```
|
||||||
|
|
||||||
|
or manually clone the repo and then run `npm install`.
|
||||||
|
|
||||||
|
|
||||||
|
### Migrations
|
||||||
|
|
||||||
|
Run the following command to run startup migrations.
|
||||||
|
|
||||||
|
```js
|
||||||
|
adonis migration:run
|
||||||
|
```
|
||||||
21
server/ace
Normal file
21
server/ace
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Ace Commands
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The ace file is just a regular Javascript file but with no extension. You
|
||||||
|
| can call `node ace` followed by the command name and it just works.
|
||||||
|
|
|
||||||
|
| Also you can use `adonis` followed by the command name, since the adonis
|
||||||
|
| global proxies all the ace commands.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { Ignitor } = require('@adonisjs/ignitor')
|
||||||
|
|
||||||
|
new Ignitor(require('@adonisjs/fold'))
|
||||||
|
.appRoot(__dirname)
|
||||||
|
.fireAce()
|
||||||
|
.catch(console.error)
|
||||||
17
server/app/Controllers/Http/DDragonController.js
Normal file
17
server/app/Controllers/Http/DDragonController.js
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const Jax = use('App/Lib/Jax')
|
||||||
|
|
||||||
|
class DDragonController {
|
||||||
|
/**
|
||||||
|
* POST - Return infos about all static Ddragon data
|
||||||
|
*/
|
||||||
|
async index({ request, response }) {
|
||||||
|
console.log('DDragon Request')
|
||||||
|
const endpoint = request.input('endpoint')
|
||||||
|
const result = await Jax.DDragon[endpoint].list()
|
||||||
|
response.json(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DDragonController
|
||||||
93
server/app/Controllers/Http/SummonerController.js
Normal file
93
server/app/Controllers/Http/SummonerController.js
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const Match = use('App/Models/Match')
|
||||||
|
const Jax = use('App/Lib/Jax')
|
||||||
|
|
||||||
|
class SummonerController {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST Endpoint : get summoner data
|
||||||
|
*/
|
||||||
|
async api({ request, response }) {
|
||||||
|
const summoner = request.input('summoner')
|
||||||
|
const region = request.input('region')
|
||||||
|
|
||||||
|
const data = await this.getSummonerData(summoner, region)
|
||||||
|
response.json(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all the data about the searched Summoner
|
||||||
|
* @param summoner
|
||||||
|
* @param region
|
||||||
|
*/
|
||||||
|
async getSummonerData(summoner, region) {
|
||||||
|
console.time('all')
|
||||||
|
|
||||||
|
console.log(summoner, region)
|
||||||
|
|
||||||
|
const regexSummonerName = new RegExp('^[0-9\\p{L} _\\.]+$', 'u')
|
||||||
|
if (!regexSummonerName.exec(summoner)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalJSON = {}
|
||||||
|
Jax.regionName = region
|
||||||
|
|
||||||
|
try {
|
||||||
|
const account = await Jax.Summoner.summonerName(summoner)
|
||||||
|
|
||||||
|
// Check if the summoner is found
|
||||||
|
if (!account) return null
|
||||||
|
|
||||||
|
finalJSON.account = account
|
||||||
|
|
||||||
|
const ranked = await Jax.League.summonerID(account.id)
|
||||||
|
const soloQ = ranked.filter(e => e.queueType === 'RANKED_SOLO_5x5')
|
||||||
|
finalJSON.soloQ = soloQ.length ? soloQ[0] : null;
|
||||||
|
|
||||||
|
console.time('getMatches')
|
||||||
|
const { matches } = await Jax.Matchlist.accountID(account.accountId)
|
||||||
|
const gameIds = matches.slice(0, 10).map(({ gameId }) => gameId)
|
||||||
|
|
||||||
|
let matchesDetails = []
|
||||||
|
const matchesToGetFromRiot = []
|
||||||
|
for (let i = 0; i < gameIds.length; ++i) {
|
||||||
|
const matchSaved = await Match.where({ gameId: gameIds[i] }).first()
|
||||||
|
if (matchSaved) {
|
||||||
|
console.log('match in mongodb')
|
||||||
|
matchesDetails.push(matchSaved)
|
||||||
|
} else {
|
||||||
|
console.log('match to get from api')
|
||||||
|
matchesToGetFromRiot.push(gameIds[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const requests = matchesToGetFromRiot.map(Jax.Match.get)
|
||||||
|
const matchesFromApi = await Promise.all(requests)
|
||||||
|
matchesDetails = [...matchesDetails, ...matchesFromApi]
|
||||||
|
|
||||||
|
/* Save all matches in db */
|
||||||
|
for (const match of matchesFromApi) {
|
||||||
|
await Match.create(match)
|
||||||
|
console.log('match saved')
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sort 10 matches */
|
||||||
|
matchesDetails.sort((a, b) => (a.gameCreation < b.gameCreation) ? 1 : -1)
|
||||||
|
|
||||||
|
finalJSON.matchesDetails = matchesDetails
|
||||||
|
finalJSON.allMatches = matches
|
||||||
|
|
||||||
|
console.timeEnd('getMatches')
|
||||||
|
console.timeEnd('all')
|
||||||
|
return finalJSON
|
||||||
|
} catch (error) {
|
||||||
|
console.log('username not found')
|
||||||
|
console.log(error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = SummonerController
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import got from 'got'
|
const got = require('got')
|
||||||
|
|
||||||
class DDragonRequest {
|
class DDragonRequest {
|
||||||
constructor(endpoint, type, version) {
|
constructor(endpoint, type, version) {
|
||||||
|
|
@ -30,4 +30,4 @@ class DDragonRequest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DDragonRequest
|
module.exports = DDragonRequest
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import DDragonRequest from '../../DDragonRequest'
|
const DDragonRequest = require('../../DDragonRequest')
|
||||||
|
|
||||||
class DDragonChampionEndpoint {
|
class DDragonChampionEndpoint {
|
||||||
constructor(version) {
|
constructor(version) {
|
||||||
|
|
@ -14,4 +14,4 @@ class DDragonChampionEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DDragonChampionEndpoint
|
module.exports = DDragonChampionEndpoint
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import DDragonRequest from '../../DDragonRequest'
|
const DDragonRequest = require('../../DDragonRequest')
|
||||||
|
|
||||||
class DDragonVersionEndpoint {
|
class DDragonVersionEndpoint {
|
||||||
list() {
|
list() {
|
||||||
|
|
@ -10,4 +10,4 @@ class DDragonVersionEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DDragonVersionEndpoint
|
module.exports = DDragonVersionEndpoint
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import JaxRequest from '../JaxRequest'
|
const JaxRequest = require('../JaxRequest')
|
||||||
|
|
||||||
class LeagueEndpoint {
|
class LeagueEndpoint {
|
||||||
constructor(limiter, region) {
|
constructor(limiter, region) {
|
||||||
|
|
@ -15,4 +15,4 @@ class LeagueEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LeagueEndpoint
|
module.exports = LeagueEndpoint
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import JaxRequest from '../JaxRequest'
|
const JaxRequest = require('../JaxRequest')
|
||||||
|
|
||||||
class MatchEndpoint {
|
class MatchEndpoint {
|
||||||
constructor(limiter, region) {
|
constructor(limiter, region) {
|
||||||
|
|
@ -17,4 +17,4 @@ class MatchEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MatchEndpoint
|
module.exports = MatchEndpoint
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import JaxRequest from '../JaxRequest'
|
const JaxRequest = require('../JaxRequest')
|
||||||
|
|
||||||
class MatchlistEndpoint {
|
class MatchlistEndpoint {
|
||||||
constructor(limiter, region) {
|
constructor(limiter, region) {
|
||||||
|
|
@ -15,4 +15,4 @@ class MatchlistEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MatchlistEndpoint
|
module.exports = MatchlistEndpoint
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import JaxRequest from '../JaxRequest'
|
const JaxRequest = require('../JaxRequest')
|
||||||
|
|
||||||
class SummonerEndpoint {
|
class SummonerEndpoint {
|
||||||
constructor(limiter, region) {
|
constructor(limiter, region) {
|
||||||
|
|
@ -15,4 +15,4 @@ class SummonerEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SummonerEndpoint
|
module.exports = SummonerEndpoint
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
import RiotRateLimiter from 'riot-ratelimiter'
|
const Env = use('Env')
|
||||||
import { STRATEGY } from 'riot-ratelimiter/dist/RateLimiter'
|
const RiotRateLimiter = require('riot-ratelimiter')
|
||||||
|
const { STRATEGY } = require('riot-ratelimiter/dist/RateLimiter')
|
||||||
|
const LeagueEndpoint = require('./Endpoints/LeagueEndpoint')
|
||||||
|
const MatchEndpoint = require('./Endpoints/MatchEndpoint')
|
||||||
|
const MatchlistEndpoint = require('./Endpoints/MatchlistEndpoint')
|
||||||
|
const SummonerEndpoint = require('./Endpoints/SummonerEndpoint')
|
||||||
|
|
||||||
|
const DDragonVersionEndpoint = require('./Endpoints/DDragonEndpoints/DDragonVersionEndpoint')
|
||||||
import LeagueEndpoint from './Endpoints/LeagueEndpoint'
|
const DDragonChampionEndpoint = require('./Endpoints/DDragonEndpoints/DDragonChampionEndpoint')
|
||||||
import MatchEndpoint from './Endpoints/MatchEndpoint'
|
|
||||||
import MatchlistEndpoint from './Endpoints/MatchlistEndpoint'
|
|
||||||
import SummonerEndpoint from './Endpoints/SummonerEndpoint'
|
|
||||||
|
|
||||||
import DDragonVersionEndpoint from './Endpoints/DDragonEndpoints/DDragonVersionEndpoint'
|
|
||||||
import DDragonChampionEndpoint from './Endpoints/DDragonEndpoints/DDragonChampionEndpoint'
|
|
||||||
|
|
||||||
class Jax {
|
class Jax {
|
||||||
constructor(key = process.env.API_KEY, region = 'euw1') {
|
constructor(key = Env.get('API_KEY'), region = 'euw1') {
|
||||||
|
|
||||||
this.key = key
|
this.key = key
|
||||||
const limiterOptions = {
|
const limiterOptions = {
|
||||||
|
|
@ -49,6 +48,4 @@ class Jax {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = new Jax()
|
||||||
Jax: new Jax()
|
|
||||||
}
|
|
||||||
|
|
@ -22,4 +22,4 @@ class JaxRequest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default JaxRequest
|
module.exports = JaxRequest
|
||||||
17
server/app/Middleware/ConvertEmptyStringsToNull.js
Normal file
17
server/app/Middleware/ConvertEmptyStringsToNull.js
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
class ConvertEmptyStringsToNull {
|
||||||
|
async handle ({ request }, next) {
|
||||||
|
if (Object.keys(request.body).length) {
|
||||||
|
request.body = Object.assign(
|
||||||
|
...Object.keys(request.body).map(key => ({
|
||||||
|
[key]: request.body[key] !== '' ? request.body[key] : null
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ConvertEmptyStringsToNull
|
||||||
9
server/app/Models/Match.js
Normal file
9
server/app/Models/Match.js
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
|
||||||
|
const Model = use('Model')
|
||||||
|
|
||||||
|
class Match extends Model {
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Match
|
||||||
16
server/app/Models/Traits/NoTimestamp.js
Normal file
16
server/app/Models/Traits/NoTimestamp.js
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
class NoTimestamp {
|
||||||
|
register (Model) {
|
||||||
|
Object.defineProperties(Model, {
|
||||||
|
createdAtColumn: {
|
||||||
|
get: () => null,
|
||||||
|
},
|
||||||
|
updatedAtColumn: {
|
||||||
|
get: () => null,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = NoTimestamp
|
||||||
243
server/config/app.js
Normal file
243
server/config/app.js
Normal file
|
|
@ -0,0 +1,243 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/** @type {import('@adonisjs/framework/src/Env')} */
|
||||||
|
const Env = use('Env')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Application Name
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value is the name of your application and can used when you
|
||||||
|
| need to place the application's name in a email, view or
|
||||||
|
| other location.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
name: Env.get('APP_NAME', 'AdonisJs'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| App Key
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| App key is a randomly generated 16 or 32 characters long string required
|
||||||
|
| to encrypt cookies, sessions and other sensitive data.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
appKey: Env.getOrFail('APP_KEY'),
|
||||||
|
|
||||||
|
http: {
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Allow Method Spoofing
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Method spoofing allows to make requests by spoofing the http verb.
|
||||||
|
| Which means you can make a GET request but instruct the server to
|
||||||
|
| treat as a POST or PUT request. If you want this feature, set the
|
||||||
|
| below value to true.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
allowMethodSpoofing: true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Trust Proxy
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Trust proxy defines whether X-Forwarded-* headers should be trusted or not.
|
||||||
|
| When your application is behind a proxy server like nginx, these values
|
||||||
|
| are set automatically and should be trusted. Apart from setting it
|
||||||
|
| to true or false Adonis supports handful or ways to allow proxy
|
||||||
|
| values. Read documentation for that.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
trustProxy: false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Subdomains
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Offset to be used for returning subdomains for a given request.For
|
||||||
|
| majority of applications it will be 2, until you have nested
|
||||||
|
| sudomains.
|
||||||
|
| cheatsheet.adonisjs.com - offset - 2
|
||||||
|
| virk.cheatsheet.adonisjs.com - offset - 3
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
subdomainOffset: 2,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| JSONP Callback
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Default jsonp callback to be used when callback query string is missing
|
||||||
|
| in request url.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
jsonpCallback: 'callback',
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Etag
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Set etag on all HTTP response. In order to disable for selected routes,
|
||||||
|
| you can call the `response.send` with an options object as follows.
|
||||||
|
|
|
||||||
|
| response.send('Hello', { ignoreEtag: true })
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
etag: false
|
||||||
|
},
|
||||||
|
|
||||||
|
views: {
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Cache Views
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Define whether or not to cache the compiled view. Set it to true in
|
||||||
|
| production to optimize view loading time.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
cache: Env.get('CACHE_VIEWS', true)
|
||||||
|
},
|
||||||
|
|
||||||
|
static: {
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Dot Files
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Define how to treat dot files when trying to server static resources.
|
||||||
|
| By default it is set to ignore, which will pretend that dotfiles
|
||||||
|
| does not exists.
|
||||||
|
|
|
||||||
|
| Can be one of the following
|
||||||
|
| ignore, deny, allow
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
dotfiles: 'ignore',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| ETag
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Enable or disable etag generation
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
etag: true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Extensions
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Set file extension fallbacks. When set, if a file is not found, the given
|
||||||
|
| extensions will be added to the file name and search for. The first
|
||||||
|
| that exists will be served. Example: ['html', 'htm'].
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
extensions: false
|
||||||
|
},
|
||||||
|
|
||||||
|
locales: {
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Loader
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The loader to be used for fetching and updating locales. Below is the
|
||||||
|
| list of available options.
|
||||||
|
|
|
||||||
|
| file, database
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
loader: 'file',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Default Locale
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Default locale to be used by Antl provider. You can always switch drivers
|
||||||
|
| in runtime or use the official Antl middleware to detect the driver
|
||||||
|
| based on HTTP headers/query string.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
locale: 'en'
|
||||||
|
},
|
||||||
|
|
||||||
|
logger: {
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Transport
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Transport to be used for logging messages. You can have multiple
|
||||||
|
| transports using same driver.
|
||||||
|
|
|
||||||
|
| Available drivers are: `file` and `console`.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
transport: 'console',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Console Transport
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Using `console` driver for logging. This driver writes to `stdout`
|
||||||
|
| and `stderr`
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
console: {
|
||||||
|
driver: 'console',
|
||||||
|
name: 'adonis-app',
|
||||||
|
level: 'info'
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| File Transport
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| File transport uses file driver and writes log messages for a given
|
||||||
|
| file inside `tmp` directory for your app.
|
||||||
|
|
|
||||||
|
| For a different directory, set an absolute path for the filename.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
file: {
|
||||||
|
driver: 'file',
|
||||||
|
name: 'adonis-app',
|
||||||
|
filename: 'adonis.log',
|
||||||
|
level: 'info'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Generic Cookie Options
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The following cookie options are generic settings used by AdonisJs to create
|
||||||
|
| cookies. However, some parts of the application like `sessions` can have
|
||||||
|
| separate settings for cookies inside `config/session.js`.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
cookie: {
|
||||||
|
httpOnly: true,
|
||||||
|
sameSite: false,
|
||||||
|
path: '/',
|
||||||
|
maxAge: 7200
|
||||||
|
}
|
||||||
|
}
|
||||||
94
server/config/auth.js
Normal file
94
server/config/auth.js
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/** @type {import('@adonisjs/framework/src/Env')} */
|
||||||
|
const Env = use('Env')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Authenticator
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Authentication is a combination of serializer and scheme with extra
|
||||||
|
| config to define on how to authenticate a user.
|
||||||
|
|
|
||||||
|
| Available Schemes - basic, session, jwt, api
|
||||||
|
| Available Serializers - lucid, database
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
authenticator: 'jwt',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Session
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Session authenticator makes use of sessions to authenticate a user.
|
||||||
|
| Session authentication is always persistent.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
session: {
|
||||||
|
serializer: 'lucid',
|
||||||
|
model: 'App/Models/User',
|
||||||
|
scheme: 'session',
|
||||||
|
uid: 'email',
|
||||||
|
password: 'password'
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Basic Auth
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The basic auth authenticator uses basic auth header to authenticate a
|
||||||
|
| user.
|
||||||
|
|
|
||||||
|
| NOTE:
|
||||||
|
| This scheme is not persistent and users are supposed to pass
|
||||||
|
| login credentials on each request.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
basic: {
|
||||||
|
serializer: 'lucid',
|
||||||
|
model: 'App/Models/User',
|
||||||
|
scheme: 'basic',
|
||||||
|
uid: 'email',
|
||||||
|
password: 'password'
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Jwt
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The jwt authenticator works by passing a jwt token on each HTTP request
|
||||||
|
| via HTTP `Authorization` header.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
jwt: {
|
||||||
|
serializer: 'lucid',
|
||||||
|
model: 'App/Models/User',
|
||||||
|
scheme: 'jwt',
|
||||||
|
uid: 'email',
|
||||||
|
password: 'password',
|
||||||
|
options: {
|
||||||
|
secret: Env.get('APP_KEY')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Api
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The Api scheme makes use of API personal tokens to authenticate a user.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
api: {
|
||||||
|
serializer: 'lucid',
|
||||||
|
model: 'App/Models/User',
|
||||||
|
scheme: 'api',
|
||||||
|
uid: 'email',
|
||||||
|
password: 'password'
|
||||||
|
}
|
||||||
|
}
|
||||||
157
server/config/bodyParser.js
Normal file
157
server/config/bodyParser.js
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| JSON Parser
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Below settings are applied when the request body contains a JSON payload.
|
||||||
|
| If you want body parser to ignore JSON payloads, then simply set `types`
|
||||||
|
| to an empty array.
|
||||||
|
*/
|
||||||
|
json: {
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| limit
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Defines the limit of JSON that can be sent by the client. If payload
|
||||||
|
| is over 1mb it will not be processed.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
limit: '1mb',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| strict
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| When `strict` is set to true, body parser will only parse Arrays and
|
||||||
|
| Object. Otherwise everything parseable by `JSON.parse` is parsed.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
strict: true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| types
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Which content types are processed as JSON payloads. You are free to
|
||||||
|
| add your own types here, but the request body should be parseable
|
||||||
|
| by `JSON.parse` method.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
types: [
|
||||||
|
'application/json',
|
||||||
|
'application/json-patch+json',
|
||||||
|
'application/vnd.api+json',
|
||||||
|
'application/csp-report'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Raw Parser
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
raw: {
|
||||||
|
types: [
|
||||||
|
'text/*'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Form Parser
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
form: {
|
||||||
|
types: [
|
||||||
|
'application/x-www-form-urlencoded'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Files Parser
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
files: {
|
||||||
|
types: [
|
||||||
|
'multipart/form-data'
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Max Size
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Below value is the max size of all the files uploaded to the server. It
|
||||||
|
| is validated even before files have been processed and hard exception
|
||||||
|
| is thrown.
|
||||||
|
|
|
||||||
|
| Consider setting a reasonable value here, otherwise people may upload GB's
|
||||||
|
| of files which will keep your server busy.
|
||||||
|
|
|
||||||
|
| Also this value is considered when `autoProcess` is set to true.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
maxSize: '20mb',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Auto Process
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Whether or not to auto-process files. Since HTTP servers handle files via
|
||||||
|
| couple of specific endpoints. It is better to set this value off and
|
||||||
|
| manually process the files when required.
|
||||||
|
|
|
||||||
|
| This value can contain a boolean or an array of route patterns
|
||||||
|
| to be autoprocessed.
|
||||||
|
*/
|
||||||
|
autoProcess: true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Process Manually
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The list of routes that should not process files and instead rely on
|
||||||
|
| manual process. This list should only contain routes when autoProcess
|
||||||
|
| is to true. Otherwise everything is processed manually.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
processManually: []
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Temporary file name
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Define a function, which should return a string to be used as the
|
||||||
|
| tmp file name.
|
||||||
|
|
|
||||||
|
| If not defined, Bodyparser will use `uuid` as the tmp file name.
|
||||||
|
|
|
||||||
|
| To be defined as. If you are defining the function, then do make sure
|
||||||
|
| to return a value from it.
|
||||||
|
|
|
||||||
|
| tmpFileName () {
|
||||||
|
| return 'some-unique-value'
|
||||||
|
| }
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
97
server/config/cors.js
Normal file
97
server/config/cors.js
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Origin
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Set a list of origins to be allowed. The value can be one of the following
|
||||||
|
|
|
||||||
|
| Boolean: true - Allow current request origin
|
||||||
|
| Boolean: false - Disallow all
|
||||||
|
| String - Comma separated list of allowed origins
|
||||||
|
| Array - An array of allowed origins
|
||||||
|
| String: * - A wildcard to allow current request origin
|
||||||
|
| Function - Receives the current origin and should return one of the above values.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
origin: (origin) => {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (origin.includes('leaguestats.gg')) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Methods
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| HTTP methods to be allowed. The value can be one of the following
|
||||||
|
|
|
||||||
|
| String - Comma separated list of allowed methods
|
||||||
|
| Array - An array of allowed methods
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
methods: ['GET', 'PUT', 'PATCH', 'POST', 'DELETE'],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Headers
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| List of headers to be allowed via Access-Control-Request-Headers header.
|
||||||
|
| The value can be one of the following.
|
||||||
|
|
|
||||||
|
| Boolean: true - Allow current request headers
|
||||||
|
| Boolean: false - Disallow all
|
||||||
|
| String - Comma separated list of allowed headers
|
||||||
|
| Array - An array of allowed headers
|
||||||
|
| String: * - A wildcard to allow current request headers
|
||||||
|
| Function - Receives the current header and should return one of the above values.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
headers: true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Expose Headers
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| A list of headers to be exposed via `Access-Control-Expose-Headers`
|
||||||
|
| header. The value can be one of the following.
|
||||||
|
|
|
||||||
|
| Boolean: false - Disallow all
|
||||||
|
| String: Comma separated list of allowed headers
|
||||||
|
| Array - An array of allowed headers
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
exposeHeaders: false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Credentials
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Define Access-Control-Allow-Credentials header. It should always be a
|
||||||
|
| boolean.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
credentials: false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| MaxAge
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Define Access-Control-Allow-Max-Age
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
maxAge: 90
|
||||||
|
}
|
||||||
107
server/config/database.js
Normal file
107
server/config/database.js
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/** @type {import('@adonisjs/framework/src/Env')} */
|
||||||
|
const Env = use('Env')
|
||||||
|
|
||||||
|
/** @type {import('@adonisjs/ignitor/src/Helpers')} */
|
||||||
|
const Helpers = use('Helpers')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Default Connection
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Connection defines the default connection settings to be used while
|
||||||
|
| interacting with SQL databases.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
connection: Env.get('DB_CONNECTION', 'mongodb'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Sqlite
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Sqlite is a flat file database and can be a good choice for a development
|
||||||
|
| environment.
|
||||||
|
|
|
||||||
|
| npm i --save sqlite3
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
sqlite: {
|
||||||
|
client: 'sqlite3',
|
||||||
|
connection: {
|
||||||
|
filename: Helpers.databasePath(`${Env.get('DB_DATABASE', 'development')}.sqlite`)
|
||||||
|
},
|
||||||
|
useNullAsDefault: true,
|
||||||
|
debug: Env.get('DB_DEBUG', false)
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| MySQL
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here we define connection settings for MySQL database.
|
||||||
|
|
|
||||||
|
| npm i --save mysql
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
mysql: {
|
||||||
|
client: 'mysql',
|
||||||
|
connection: {
|
||||||
|
host: Env.get('DB_HOST', 'localhost'),
|
||||||
|
port: Env.get('DB_PORT', ''),
|
||||||
|
user: Env.get('DB_USER', 'root'),
|
||||||
|
password: Env.get('DB_PASSWORD', ''),
|
||||||
|
database: Env.get('DB_DATABASE', 'adonis')
|
||||||
|
},
|
||||||
|
debug: Env.get('DB_DEBUG', false)
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| PostgreSQL
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here we define connection settings for PostgreSQL database.
|
||||||
|
|
|
||||||
|
| npm i --save pg
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
pg: {
|
||||||
|
client: 'pg',
|
||||||
|
connection: {
|
||||||
|
host: Env.get('DB_HOST', 'localhost'),
|
||||||
|
port: Env.get('DB_PORT', ''),
|
||||||
|
user: Env.get('DB_USER', 'root'),
|
||||||
|
password: Env.get('DB_PASSWORD', ''),
|
||||||
|
database: Env.get('DB_DATABASE', 'adonis')
|
||||||
|
},
|
||||||
|
debug: Env.get('DB_DEBUG', false)
|
||||||
|
},
|
||||||
|
|
||||||
|
mongodb: {
|
||||||
|
client: 'mongodb',
|
||||||
|
connectionString: Env.get('DB_CONNECTION_STRING', ''),
|
||||||
|
connection: {
|
||||||
|
host: Env.get('DB_HOST', 'localhost'),
|
||||||
|
port: Env.get('DB_PORT', 27017),
|
||||||
|
username: Env.get('DB_USER', 'admin'),
|
||||||
|
password: Env.get('DB_PASSWORD', ''),
|
||||||
|
database: Env.get('DB_DATABASE', 'adonis'),
|
||||||
|
options: {
|
||||||
|
// replicaSet: Env.get('DB_REPLICA_SET', '')
|
||||||
|
// ssl: Env.get('DB_SSL, '')
|
||||||
|
// connectTimeoutMS: Env.get('DB_CONNECT_TIMEOUT_MS', 15000),
|
||||||
|
// socketTimeoutMS: Env.get('DB_SOCKET_TIMEOUT_MS', 180000),
|
||||||
|
// w: Env.get('DB_W, 0),
|
||||||
|
// readPreference: Env.get('DB_READ_PREFERENCE', 'secondary'),
|
||||||
|
// authSource: Env.get('DB_AUTH_SOURCE', ''),
|
||||||
|
// authMechanism: Env.get('DB_AUTH_MECHANISM', ''),
|
||||||
|
// other options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
49
server/config/hash.js
Normal file
49
server/config/hash.js
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/** @type {import('@adonisjs/framework/src/Env')} */
|
||||||
|
const Env = use('Env')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Driver
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Driver to be used for hashing values. The same driver is used by the
|
||||||
|
| auth module too.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
driver: Env.get('HASH_DRIVER', 'bcrypt'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Bcrypt
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Config related to bcrypt hashing. https://www.npmjs.com/package/bcrypt
|
||||||
|
| package is used internally.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
bcrypt: {
|
||||||
|
rounds: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Argon
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Config related to argon. https://www.npmjs.com/package/argon2 package is
|
||||||
|
| used internally.
|
||||||
|
|
|
||||||
|
| Since argon is optional, you will have to install the dependency yourself
|
||||||
|
|
|
||||||
|
|============================================================================
|
||||||
|
| npm i argon2
|
||||||
|
|============================================================================
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
argon: {
|
||||||
|
type: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
21
server/database/factory.js
Normal file
21
server/database/factory.js
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Factory
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Factories are used to define blueprints for database tables or Lucid
|
||||||
|
| models. Later you can use these blueprints to seed your database
|
||||||
|
| with dummy data.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @type {import('@adonisjs/lucid/src/Factory')} */
|
||||||
|
// const Factory = use('Factory')
|
||||||
|
|
||||||
|
// Factory.blueprint('App/Models/User', (faker) => {
|
||||||
|
// return {
|
||||||
|
// username: faker.username()
|
||||||
|
// }
|
||||||
|
// })
|
||||||
18
server/database/migrations/1567863677607_match_schema.js
Normal file
18
server/database/migrations/1567863677607_match_schema.js
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/** @type {import('@adonisjs/lucid/src/Schema')} */
|
||||||
|
const Schema = use('Schema')
|
||||||
|
|
||||||
|
class MatchSchema extends Schema {
|
||||||
|
up () {
|
||||||
|
this.create('matches', (collection) => {
|
||||||
|
collection.index('gameId', {gameId: 1})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
down () {
|
||||||
|
this.drop('matches')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = MatchSchema
|
||||||
5770
server/package-lock.json
generated
5770
server/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,32 +1,37 @@
|
||||||
{
|
{
|
||||||
"name": "leaguestats-backend",
|
"name": "adonis-api-app",
|
||||||
"version": "0.1.0",
|
"version": "4.1.0",
|
||||||
"description": "",
|
"adonis-version": "4.1.0",
|
||||||
|
"description": "Adonisjs boilerplate for API server with pre-configured JWT",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "babel -d ./build ./src -s",
|
"start": "node server.js",
|
||||||
"clean": "rm -rf build",
|
"test": "node ace test"
|
||||||
"dev": "./node_modules/.bin/cross-env NODE_ENV=development nodemon --exec babel-node src/server.js"
|
|
||||||
},
|
},
|
||||||
"author": "kalane",
|
"keywords": [
|
||||||
"license": "ISC",
|
"adonisjs",
|
||||||
|
"adonis-app"
|
||||||
|
],
|
||||||
|
"author": "",
|
||||||
|
"license": "UNLICENSED",
|
||||||
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.5.5",
|
"@adonisjs/ace": "^5.0.8",
|
||||||
"body-parser": "^1.19.0",
|
"@adonisjs/auth": "^3.0.7",
|
||||||
"cors": "^2.8.5",
|
"@adonisjs/bodyparser": "^2.0.5",
|
||||||
"dotenv": "^7.0.0",
|
"@adonisjs/cors": "^1.0.7",
|
||||||
"express": "^4.17.1",
|
"@adonisjs/fold": "^4.0.9",
|
||||||
|
"@adonisjs/framework": "^5.0.9",
|
||||||
|
"@adonisjs/ignitor": "^2.0.8",
|
||||||
|
"@adonisjs/lucid": "^6.1.3",
|
||||||
"got": "^9.6.0",
|
"got": "^9.6.0",
|
||||||
|
"lucid-mongo": "^3.1.6",
|
||||||
|
"mongodb-core": "^3.2.7",
|
||||||
"request": "^2.88.0",
|
"request": "^2.88.0",
|
||||||
"response-time": "^2.3.2",
|
|
||||||
"riot-ratelimiter": "^0.1.5"
|
"riot-ratelimiter": "^0.1.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {},
|
||||||
"@babel/cli": "^7.5.5",
|
"autoload": {
|
||||||
"@babel/core": "^7.5.5",
|
"App": "./app"
|
||||||
"@babel/node": "^7.5.5",
|
|
||||||
"@babel/plugin-transform-runtime": "^7.5.5",
|
|
||||||
"@babel/preset-env": "^7.5.5",
|
|
||||||
"cross-env": "^5.2.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
25
server/server.js
Normal file
25
server/server.js
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Http server
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This file bootstraps Adonisjs to start the HTTP server. You are free to
|
||||||
|
| customize the process of booting the http server.
|
||||||
|
|
|
||||||
|
| """ Loading ace commands """
|
||||||
|
| At times you may want to load ace commands when starting the HTTP server.
|
||||||
|
| Same can be done by chaining `loadCommands()` method after
|
||||||
|
|
|
||||||
|
| """ Preloading files """
|
||||||
|
| Also you can preload files by calling `preLoad('path/to/file')` method.
|
||||||
|
| Make sure to pass a relative path from the project root.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { Ignitor } = require('@adonisjs/ignitor')
|
||||||
|
|
||||||
|
new Ignitor(require('@adonisjs/fold'))
|
||||||
|
.appRoot(__dirname)
|
||||||
|
.fireHttpServer()
|
||||||
|
.catch(console.error)
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
require('dotenv').config({ path: __dirname + '/./../.env' })
|
|
||||||
const express = require('express')
|
|
||||||
const bodyParser = require('body-parser')
|
|
||||||
const responseTime = require('response-time')
|
|
||||||
const cors = require('cors')
|
|
||||||
const app = express()
|
|
||||||
import { Jax } from "./Jax"
|
|
||||||
|
|
||||||
/* Set Port */
|
|
||||||
app.set('port', (process.env.PORT || 3333))
|
|
||||||
|
|
||||||
/* Setup Cors */
|
|
||||||
app.use(cors({
|
|
||||||
origin: [
|
|
||||||
'http://localhost:8080',
|
|
||||||
'https://leaguestats-gg.netlify.com',
|
|
||||||
'https://leaguestats.valentinkaelin.ch/',
|
|
||||||
'https://leaguestats.gg'
|
|
||||||
]
|
|
||||||
}))
|
|
||||||
|
|
||||||
/* To retrieve data of post request */
|
|
||||||
app.use(bodyParser.json()) // to support JSON-encoded bodies
|
|
||||||
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
|
|
||||||
extended: true
|
|
||||||
}))
|
|
||||||
|
|
||||||
// Create a middleware that adds a X-Response-Time header to responses
|
|
||||||
app.use(responseTime())
|
|
||||||
|
|
||||||
/* Launch app */
|
|
||||||
app.listen(app.get('port'), () => {
|
|
||||||
console.log(`RiotAPI app listening on port ${app.get('port')}!`)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Send data of a summoner
|
|
||||||
app.post('/api', async function (req, res) {
|
|
||||||
console.log('API Request')
|
|
||||||
console.log(req.body.summoner, req.body.region)
|
|
||||||
console.time('all')
|
|
||||||
|
|
||||||
/* Check if the summonerName is correct before fetching Riot API */
|
|
||||||
const regexSummonerName = new RegExp('^[0-9\\p{L} _\\.]+$', 'u')
|
|
||||||
if (!regexSummonerName.exec(req.body.summoner)) {
|
|
||||||
return res.send(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
const finalJSON = {}
|
|
||||||
Jax.regionName = req.body.region
|
|
||||||
|
|
||||||
try {
|
|
||||||
const account = await Jax.Summoner.summonerName(req.body.summoner)
|
|
||||||
|
|
||||||
// Check if the summoner is found
|
|
||||||
if (!account) return res.send(null)
|
|
||||||
|
|
||||||
finalJSON.account = account
|
|
||||||
|
|
||||||
const ranked = await Jax.League.summonerID(account.id)
|
|
||||||
const soloQ = ranked.filter(e => e.queueType === 'RANKED_SOLO_5x5')
|
|
||||||
finalJSON.soloQ = soloQ.length ? soloQ[0] : null;
|
|
||||||
|
|
||||||
console.time('getMatches')
|
|
||||||
const { matches } = await Jax.Matchlist.accountID(account.accountId)
|
|
||||||
const gameIds = matches.slice(0, 10).map(({ gameId }) => gameId)
|
|
||||||
const requests = gameIds.map(Jax.Match.get)
|
|
||||||
const results = await Promise.all(requests)
|
|
||||||
finalJSON.matchesDetails = results
|
|
||||||
finalJSON.allMatches = matches
|
|
||||||
|
|
||||||
res.send(finalJSON)
|
|
||||||
console.timeEnd('getMatches')
|
|
||||||
console.timeEnd('all')
|
|
||||||
} catch (error) {
|
|
||||||
console.log('username not found')
|
|
||||||
res.send(null)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
/* Get static file from Riot API */
|
|
||||||
app.post('/ddragon', async function (req, res) {
|
|
||||||
console.log('DDragon Request')
|
|
||||||
const endpoint = req.body.endpoint
|
|
||||||
const result = await Jax.DDragon[endpoint].list()
|
|
||||||
res.send(result)
|
|
||||||
})
|
|
||||||
57
server/start/app.js
Normal file
57
server/start/app.js
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Providers
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Providers are building blocks for your Adonis app. Anytime you install
|
||||||
|
| a new Adonis specific package, chances are you will register the
|
||||||
|
| provider here.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
const providers = [
|
||||||
|
'@adonisjs/framework/providers/AppProvider',
|
||||||
|
'@adonisjs/bodyparser/providers/BodyParserProvider',
|
||||||
|
'@adonisjs/cors/providers/CorsProvider',
|
||||||
|
'lucid-mongo/providers/LucidMongoProvider'
|
||||||
|
]
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Ace Providers
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Ace providers are required only when running ace commands. For example
|
||||||
|
| Providers for migrations, tests etc.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
const aceProviders = [
|
||||||
|
'lucid-mongo/providers/MigrationsProvider'
|
||||||
|
]
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Aliases
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Aliases are short unique names for IoC container bindings. You are free
|
||||||
|
| to create your own aliases.
|
||||||
|
|
|
||||||
|
| For example:
|
||||||
|
| { Route: 'Adonis/Src/Route' }
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
const aliases = {}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Commands
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you store ace commands for your package
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
const commands = []
|
||||||
|
|
||||||
|
module.exports = { providers, aceProviders, aliases, commands }
|
||||||
60
server/start/kernel.js
Normal file
60
server/start/kernel.js
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/** @type {import('@adonisjs/framework/src/Server')} */
|
||||||
|
const Server = use('Server')
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Global Middleware
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Global middleware are executed on each http request only when the routes
|
||||||
|
| match.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
const globalMiddleware = [
|
||||||
|
'Adonis/Middleware/BodyParser',
|
||||||
|
'App/Middleware/ConvertEmptyStringsToNull'
|
||||||
|
]
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Named Middleware
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Named middleware is key/value object to conditionally add middleware on
|
||||||
|
| specific routes or group of routes.
|
||||||
|
|
|
||||||
|
| // define
|
||||||
|
| {
|
||||||
|
| auth: 'Adonis/Middleware/Auth'
|
||||||
|
| }
|
||||||
|
|
|
||||||
|
| // use
|
||||||
|
| Route.get().middleware('auth')
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
const namedMiddleware = {
|
||||||
|
auth: 'Adonis/Middleware/Auth',
|
||||||
|
guest: 'Adonis/Middleware/AllowGuestOnly'
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Server Middleware
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Server level middleware are executed even when route for a given URL is
|
||||||
|
| not registered. Features like `static assets` and `cors` needs better
|
||||||
|
| control over request lifecycle.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
const serverMiddleware = [
|
||||||
|
// 'Adonis/Middleware/Static',
|
||||||
|
'Adonis/Middleware/Cors'
|
||||||
|
]
|
||||||
|
|
||||||
|
Server
|
||||||
|
.registerGlobal(globalMiddleware)
|
||||||
|
.registerNamed(namedMiddleware)
|
||||||
|
.use(serverMiddleware)
|
||||||
29
server/start/routes.js
Normal file
29
server/start/routes.js
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Routes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Http routes are entry points to your web application. You can create
|
||||||
|
| routes for different URLs and bind Controller actions to them.
|
||||||
|
|
|
||||||
|
| A complete guide on routing is available here.
|
||||||
|
| http://adonisjs.com/docs/4.1/routing
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @type {typeof import('@adonisjs/framework/src/Route/Manager')} */
|
||||||
|
const Route = use('Route')
|
||||||
|
|
||||||
|
const Match = use('App/Models/Match')
|
||||||
|
|
||||||
|
Route.get('/', async () => {
|
||||||
|
return {
|
||||||
|
greeting: 'Hello world in JSON',
|
||||||
|
match: await Match.first()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Route.post('/api', 'SummonerController.api')
|
||||||
|
Route.post('/ddragon', 'DDragonController.index')
|
||||||
Loading…
Reference in a new issue