diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 75aece7..ff1a32f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -56,15 +56,15 @@ jobs: needs: test if: github.ref == 'refs/heads/main' steps: - - name: Deploy using ssh - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.SERVER_HOST }} - username: ${{ secrets.SERVER_USERNAME }} - key: ${{ secrets.SERVER_KEY }} - port: 22 - script: | - cd ~/Git/pokerio-server - git pull origin main - yarn - yarn production + - name: Deploy using ssh + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.SERVER_HOST }} + username: ${{ secrets.SERVER_USERNAME }} + key: ${{ secrets.SERVER_KEY }} + port: 22 + script: | + cd ~/Git/pokerio-server + git pull origin main + yarn + yarn production diff --git a/README.md b/README.md index 461ca24..298d189 100644 --- a/README.md +++ b/README.md @@ -6,17 +6,34 @@ [![Tests](https://github.com/poker-io/pokerio-server/actions/workflows/test.yml/badge.svg)](https://github.com/poker-io/pokerio-server/blob/main/.github/workflows/test.yml) [![codecov](https://codecov.io/gh/poker-io/pokerio-server/branch/main/graph/badge.svg?token=4QCZNOWFZJ)](https://codecov.io/gh/poker-io/pokerio-server) -## Building +## Requirements -Run `yarn install`. +Make sure you're using node version 18 or newer. To install the appropriate +version follow the instructions on nodejs.org. -## Running +To install dependencies run: + +``` +yarn install +``` + +Remember to add the `serviceAccount.json` file from Firebase under `src/` as +well as a `secrets.ts` file that contains login credentials for the database. +It should be similar to this: + +```ts +export const user = 'pokerio-user' +export const password = 'pokerio-password' -First you have to add firebase service account json file in src/ as serviceAccount.json. +``` + +## Running Run `yarn start`. +The app will attempt to connect to a Postgres database using the details +provided in `databaseConnection.ts`. + ## Testing We use Jest for testing. To run it, simply type `yarn test`. -Make sure your Node's version is > v18 (`nvm install v18.15.0` to install appropriate version). diff --git a/src/app.ts b/src/app.ts index 07199fa..2033ede 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,9 +1,9 @@ import express from 'express' import { isCelebrateError } from 'celebrate' -import { rateLimit } from 'express-rate-limit' import joinGame from './routes/joinGame' import createGame from './routes/createGame' +import { rateLimiter } from './utils/rateLimiter' export const app = express() export const port = 42069 @@ -38,17 +38,10 @@ const errorHandling = (error, req, res, next) => { return next(error) } -const rateLimiter = rateLimit({ - windowMs: 60 * 1000, // 1 minute - max: 100, // limit each IP to 100 requests per windowMs -}) - -app.get('/status', (req, res) => { +app.get('/status', rateLimiter, (req, res) => { res.send('OK') }) -app.use(rateLimiter) - app.use(joinGame) app.use(createGame) diff --git a/src/index.ts b/src/index.ts index d6dd788..7402bb5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ import { app, port } from './app.js' -import { databaseInit } from './databaseConnection' +import { databaseInit } from './utils/databaseConnection' databaseInit() .then(() => { diff --git a/src/routes/createGame.ts b/src/routes/createGame.ts index d53f6f4..0257f4e 100644 --- a/src/routes/createGame.ts +++ b/src/routes/createGame.ts @@ -1,17 +1,19 @@ -import { getClient } from '../databaseConnection' +import { getClient } from '../utils/databaseConnection' import { celebrate, Joi, Segments } from 'celebrate' import { startingFundsDefault, smallBlindDefault, type newGameInfo, } from '../app' -import { verifyFCMToken } from '../firebase' +import { verifyFCMToken } from '../utils/firebase' import express, { type Router } from 'express' +import { rateLimiter } from '../utils/rateLimiter' const router: Router = express.Router() router.get( '/createGame', + rateLimiter, celebrate({ [Segments.QUERY]: Joi.object().keys({ creatorToken: Joi.string() diff --git a/src/routes/joinGame.ts b/src/routes/joinGame.ts index a3cd9a6..7ba7369 100644 --- a/src/routes/joinGame.ts +++ b/src/routes/joinGame.ts @@ -1,15 +1,17 @@ -import { getClient } from '../databaseConnection' +import { getClient } from '../utils/databaseConnection' import { celebrate, Joi, Segments } from 'celebrate' import sha256 from 'crypto-js/sha256' import { getMessaging } from 'firebase-admin/messaging' import { type gameSettings } from '../app' -import { verifyFCMToken } from '../firebase' +import { verifyFCMToken } from '../utils/firebase' import express, { type Router } from 'express' +import { rateLimiter } from '../utils/rateLimiter' const router: Router = express.Router() router.get( '/joinGame', + rateLimiter, celebrate({ [Segments.QUERY]: Joi.object().keys({ playerToken: Joi.string().required().min(1).max(250).label('playerToken'), diff --git a/src/tests/createGame.test.ts b/src/tests/createGame.test.ts index 302f987..3154aa9 100644 --- a/src/tests/createGame.test.ts +++ b/src/tests/createGame.test.ts @@ -1,6 +1,6 @@ import { app } from '../app' import request from 'supertest' -import { getClient } from '../databaseConnection' +import { getClient } from '../utils/databaseConnection' test('Create game, wrong args', (done) => { request(app).get('/createGame/?creatorToken=-1').expect(400).end(done) diff --git a/src/tests/databaseConnection.test.ts b/src/tests/databaseConnection.test.ts index 766dc24..2788be3 100644 --- a/src/tests/databaseConnection.test.ts +++ b/src/tests/databaseConnection.test.ts @@ -1,4 +1,4 @@ -import { databaseInit } from '../databaseConnection' +import { databaseInit } from '../utils/databaseConnection' test('Database connection', async () => { await expect(databaseInit()).resolves.not.toThrow() diff --git a/src/tests/joinGame.test.ts b/src/tests/joinGame.test.ts index 8cb69da..ce1197b 100644 --- a/src/tests/joinGame.test.ts +++ b/src/tests/joinGame.test.ts @@ -1,6 +1,6 @@ import { app } from '../app' import request from 'supertest' -import { getClient } from '../databaseConnection' +import { getClient } from '../utils/databaseConnection' import type { gameSettings } from '../app' import sha256 from 'crypto-js/sha256' diff --git a/src/databaseConnection.ts b/src/utils/databaseConnection.ts similarity index 98% rename from src/databaseConnection.ts rename to src/utils/databaseConnection.ts index 25783b8..811f99d 100644 --- a/src/databaseConnection.ts +++ b/src/utils/databaseConnection.ts @@ -1,5 +1,5 @@ import pg from 'pg' -import { user, password } from './secrets' +import { user, password } from '../secrets' // pg is a CommonJS module, so we have to do it this way for the import to work export const { Client } = pg diff --git a/src/firebase.ts b/src/utils/firebase.ts similarity index 100% rename from src/firebase.ts rename to src/utils/firebase.ts diff --git a/src/utils/rateLimiter.ts b/src/utils/rateLimiter.ts new file mode 100644 index 0000000..8336177 --- /dev/null +++ b/src/utils/rateLimiter.ts @@ -0,0 +1,6 @@ +import rateLimit from 'express-rate-limit' + +export const rateLimiter = rateLimit({ + windowMs: 60 * 1000, // 1 minute + max: 100, // limit each IP to 100 requests per windowMs +})