From 92336674aa82176b2cd643c7b9cdf158fd304736 Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Tue, 20 Aug 2024 22:30:13 +0100 Subject: [PATCH 1/9] matrix to build images --- .github/workflows/docker.yml | 17 ++++++++++------- Dockerfile | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 6884eff2..6481d45d 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -6,6 +6,9 @@ on: jobs: build: runs-on: ubuntu-latest + strategy: + matrix: + image: [backend, clickhouse] steps: - run: echo "TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV @@ -22,18 +25,18 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and push - id: docker_build + - name: Build and push (${{ matrix.image }}) + id: build-image uses: docker/build-push-action@v5 with: push: true tags: | - ghcr.io/talodev/backend:latest - ghcr.io/talodev/backend:${{ env.TAG }} - target: prod + ghcr.io/talodev/${{ matrix.image }}:latest + ghcr.io/talodev/${{ matrix.image }}:${{ env.TAG }} + target: ${{ matrix.image == 'backend' && 'prod' || '' }} - - name: Image digest - run: echo ${{ steps.docker_build.outputs.digest }} + - name: Image digest (${{ matrix.image }}) + run: echo ${{ steps.build-image.outputs.digest }} deploy: runs-on: ubuntu-latest diff --git a/Dockerfile b/Dockerfile index 3942a0ff..fa03c900 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ COPY src ./src RUN npm run build FROM base AS prod -ENV NODE_ENV production +ENV NODE_ENV=production RUN npm ci COPY --from=build /usr/backend/dist . CMD [ "node", "index.js" ] From 9d5f1a64e24e9c160d81ed04d668ea513468b472 Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Tue, 20 Aug 2024 22:53:07 +0100 Subject: [PATCH 2/9] set file --- .github/workflows/docker.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 6481d45d..712a536e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -30,6 +30,7 @@ jobs: uses: docker/build-push-action@v5 with: push: true + file: ${{ matrix.image == 'backend' && 'Dockerfile' || 'clickhouse/Dockerfile' }} tags: | ghcr.io/talodev/${{ matrix.image }}:latest ghcr.io/talodev/${{ matrix.image }}:${{ env.TAG }} From b70d304117ab7cff4918dd74fbcc3b95e6470ac3 Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Sat, 24 Aug 2024 18:21:41 +0100 Subject: [PATCH 3/9] add continuity middleware + health check api --- src/config/api-routes.ts | 4 ++++ src/middlewares/continunity-middleware.ts | 15 +++++++++++++++ .../20210725211129InitialMigration.ts | 7 ------- ...11221195514CascadeDeletePlayerAliasEvents.ts | 12 ------------ src/migrations/index.ts | 5 ----- src/services/api/health-check-api.service.ts | 17 +++++++++++++++++ .../_api/health-check-api/index.test.ts | 13 +++++++++++++ 7 files changed, 49 insertions(+), 24 deletions(-) create mode 100644 src/middlewares/continunity-middleware.ts delete mode 100644 src/migrations/20211221195514CascadeDeletePlayerAliasEvents.ts create mode 100644 src/services/api/health-check-api.service.ts create mode 100644 tests/services/_api/health-check-api/index.test.ts diff --git a/src/config/api-routes.ts b/src/config/api-routes.ts index 6689a976..ba45a449 100644 --- a/src/config/api-routes.ts +++ b/src/config/api-routes.ts @@ -1,5 +1,6 @@ import Koa, { Context, Next } from 'koa' import { service } from 'koa-clay' +import HealthCheckAPIService from '../services/api/health-check-api.service' import GameFeedbackAPIService from '../services/api/game-feedback-api.service' import GameConfigAPIService from '../services/api/game-config-api.service' import GameStatAPIService from '../services/api/game-stat-api.service' @@ -13,6 +14,7 @@ import { apiRouteAuthMiddleware, getRouteInfo } from '../middlewares/route-middl import apiKeyMiddleware from '../middlewares/api-key-middleware' import playerAuthMiddleware from '../middlewares/player-auth-middleware' import PlayerAuthAPIService from '../services/api/player-auth-api.service' +import continunityMiddleware from '../middlewares/continunity-middleware' export default (app: Koa) => { app.use(apiKeyMiddleware) @@ -27,7 +29,9 @@ export default (app: Koa) => { app.use(currentPlayerMiddleware) app.use(playerAuthMiddleware) + app.use(continunityMiddleware) + app.use(service('/v1/health-check', new HealthCheckAPIService())) app.use(service('/v1/game-feedback', new GameFeedbackAPIService())) app.use(service('/v1/game-config', new GameConfigAPIService())) app.use(service('/v1/game-stats', new GameStatAPIService())) diff --git a/src/middlewares/continunity-middleware.ts b/src/middlewares/continunity-middleware.ts new file mode 100644 index 00000000..d823ebbb --- /dev/null +++ b/src/middlewares/continunity-middleware.ts @@ -0,0 +1,15 @@ +import { isValid } from 'date-fns' +import { Context, Next } from 'koa' + +export default async (ctx: Context, next: Next): Promise => { + const header = ctx.headers['x-talo-continuity-timestamp'] + + if (header) { + const date = new Date(Number(header)) + if (isValid(date)) { + ctx.state.continuityDate = date + } + } + + await next() +} diff --git a/src/migrations/20210725211129InitialMigration.ts b/src/migrations/20210725211129InitialMigration.ts index 82745a6d..5f6246ad 100644 --- a/src/migrations/20210725211129InitialMigration.ts +++ b/src/migrations/20210725211129InitialMigration.ts @@ -26,10 +26,6 @@ export class InitialMigration extends Migration { this.addSql('create table `player_alias` (`id` int unsigned not null auto_increment primary key, `service` varchar(255) not null, `identifier` varchar(255) not null, `player_id` varchar(255) null, `created_at` datetime not null, `updated_at` datetime not null) default character set utf8mb4 engine = InnoDB') this.addSql('alter table `player_alias` add index `player_alias_player_id_index`(`player_id`)') - this.addSql('create table `event` (`id` int unsigned not null auto_increment primary key, `name` varchar(255) not null, `props` json not null, `game_id` int(11) unsigned not null, `player_alias_id` int(11) unsigned not null, `created_at` datetime not null, `updated_at` datetime not null) default character set utf8mb4 engine = InnoDB') - this.addSql('alter table `event` add index `event_game_id_index`(`game_id`)') - this.addSql('alter table `event` add index `event_player_alias_id_index`(`player_alias_id`)') - this.addSql('create table `apikey` (`id` int unsigned not null auto_increment primary key, `scopes` text not null, `game_id` int(11) unsigned not null, `created_by_user_id` int(11) unsigned not null, `created_at` datetime not null, `revoked_at` datetime null) default character set utf8mb4 engine = InnoDB') this.addSql('alter table `apikey` add index `apikey_game_id_index`(`game_id`)') this.addSql('alter table `apikey` add index `apikey_created_by_user_id_index`(`created_by_user_id`)') @@ -46,9 +42,6 @@ export class InitialMigration extends Migration { this.addSql('alter table `player_alias` add constraint `player_alias_player_id_foreign` foreign key (`player_id`) references `player` (`id`) on delete cascade') - this.addSql('alter table `event` add constraint `event_game_id_foreign` foreign key (`game_id`) references `game` (`id`) on update cascade') - this.addSql('alter table `event` add constraint `event_player_alias_id_foreign` foreign key (`player_alias_id`) references `player_alias` (`id`) on update cascade') - this.addSql('alter table `apikey` add constraint `apikey_game_id_foreign` foreign key (`game_id`) references `game` (`id`) on update cascade') this.addSql('alter table `apikey` add constraint `apikey_created_by_user_id_foreign` foreign key (`created_by_user_id`) references `user` (`id`) on update cascade') } diff --git a/src/migrations/20211221195514CascadeDeletePlayerAliasEvents.ts b/src/migrations/20211221195514CascadeDeletePlayerAliasEvents.ts deleted file mode 100644 index 1a4960f4..00000000 --- a/src/migrations/20211221195514CascadeDeletePlayerAliasEvents.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Migration } from '@mikro-orm/migrations' - -export class CascadeDeletePlayerAliasEvents extends Migration { - - async up(): Promise { - this.addSql('alter table `event` modify `player_alias_id` int(11) unsigned null;') - - this.addSql('alter table `event` drop foreign key `event_player_alias_id_foreign`;') - this.addSql('alter table `event` add constraint `event_player_alias_id_foreign` foreign key (`player_alias_id`) references `player_alias` (`id`) on delete cascade;') - } - -} diff --git a/src/migrations/index.ts b/src/migrations/index.ts index c5bcaa9b..6ccc7a1a 100644 --- a/src/migrations/index.ts +++ b/src/migrations/index.ts @@ -3,7 +3,6 @@ import { CreateDataExportsTable } from './20210926160859CreateDataExportsTable' import { CreateLeaderboardsTable } from './20211107233610CreateLeaderboardsTable' import { CreateUserTwoFactorAuthTable } from './20211205171927CreateUserTwoFactorAuthTable' import { CreateUserRecoveryCodeTable } from './20211209003017CreateUserRecoveryCodeTable' -import { CascadeDeletePlayerAliasEvents } from './20211221195514CascadeDeletePlayerAliasEvents' import { AddLeaderboardEntryHiddenColumn } from './20211224154919AddLeaderboardEntryHiddenColumn' import { CreateGameSavesTable } from './20220109144435CreateGameSavesTable' import { CreateGameActivitiesTable } from './20220125220401CreateGameActivitiesTable' @@ -49,10 +48,6 @@ export default [ name: 'CreateUserRecoveryCodeTable', class: CreateUserRecoveryCodeTable }, - { - name: 'CascadeDeletePlayerAliasEvents', - class: CascadeDeletePlayerAliasEvents - }, { name: 'AddLeaderboardEntryHiddenColumn', class: AddLeaderboardEntryHiddenColumn diff --git a/src/services/api/health-check-api.service.ts b/src/services/api/health-check-api.service.ts new file mode 100644 index 00000000..38739c9a --- /dev/null +++ b/src/services/api/health-check-api.service.ts @@ -0,0 +1,17 @@ +import { Response, Request, Routes } from 'koa-clay' +import APIService from './api-service' + +@Routes([ + { + method: 'GET' + } +]) +export default class HealthCheckAPIService extends APIService { + async index(req: Request): Promise { + console.log(req.ctx.state.continuityDate) + + return { + status: 200 + } + } +} diff --git a/tests/services/_api/health-check-api/index.test.ts b/tests/services/_api/health-check-api/index.test.ts new file mode 100644 index 00000000..3deac630 --- /dev/null +++ b/tests/services/_api/health-check-api/index.test.ts @@ -0,0 +1,13 @@ +import request from 'supertest' +import createAPIKeyAndToken from '../../../utils/createAPIKeyAndToken' + +describe('Health check API service - index', () => { + it('should return a 200', async () => { + const [, token] = await createAPIKeyAndToken([]) + + await request(global.app) + .get('/v1/health-check') + .auth(token, { type: 'bearer' }) + .expect(204) + }) +}) From 84ca7dcade9727979959e64c1565a82235af69bd Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Sun, 25 Aug 2024 11:25:02 +0100 Subject: [PATCH 4/9] update some apis to use the continuity timestamp --- src/services/api/game-feedback-api.service.ts | 3 ++ src/services/api/game-stat-api.service.ts | 4 ++ src/services/api/leaderboard-api.service.ts | 5 +- src/services/player.service.ts | 8 ++++ .../_api/game-feedback-api/post.test.ts | 22 +++++++++ tests/services/_api/game-stat-api/put.test.ts | 20 ++++++++ .../_api/leaderboard-api/post.test.ts | 46 +++++++++++++++++++ .../services/_api/player-api/identify.test.ts | 18 +++++++- 8 files changed, 124 insertions(+), 2 deletions(-) diff --git a/src/services/api/game-feedback-api.service.ts b/src/services/api/game-feedback-api.service.ts index 5e400f2c..139b6058 100644 --- a/src/services/api/game-feedback-api.service.ts +++ b/src/services/api/game-feedback-api.service.ts @@ -40,6 +40,9 @@ export default class GameFeedbackAPIService extends APIService { const feedback = new GameFeedback(category, req.ctx.state.playerAlias) feedback.comment = comment feedback.anonymised = category.anonymised + if (req.ctx.state.continuityDate) { + feedback.createdAt = req.ctx.state.continuityDate + } await em.persistAndFlush(feedback) diff --git a/src/services/api/game-stat-api.service.ts b/src/services/api/game-stat-api.service.ts index f37ff171..140672a5 100644 --- a/src/services/api/game-stat-api.service.ts +++ b/src/services/api/game-stat-api.service.ts @@ -52,6 +52,10 @@ export default class GameStatAPIService extends APIService { if (!playerStat) { playerStat = new PlayerGameStat(req.ctx.state.player, req.ctx.state.stat) + if (req.ctx.state.continuityDate) { + playerStat.createdAt = req.ctx.state.continuityDate + } + em.persist(playerStat) } diff --git a/src/services/api/leaderboard-api.service.ts b/src/services/api/leaderboard-api.service.ts index e2627443..423b90e1 100644 --- a/src/services/api/leaderboard-api.service.ts +++ b/src/services/api/leaderboard-api.service.ts @@ -37,6 +37,9 @@ export default class LeaderboardAPIService extends APIService { const entry = new LeaderboardEntry(req.ctx.state.leaderboard) entry.playerAlias = req.ctx.state.playerAlias entry.score = req.body.score + if (req.ctx.state.continuityDate) { + entry.createdAt = req.ctx.state.continuityDate + } await em.persistAndFlush(entry) @@ -67,7 +70,7 @@ export default class LeaderboardAPIService extends APIService { if ((leaderboard.sortMode === LeaderboardSortMode.ASC && score < entry.score) || (leaderboard.sortMode === LeaderboardSortMode.DESC && score > entry.score)) { entry.score = score - entry.createdAt = new Date() + entry.createdAt = req.ctx.state.continuityDate ?? new Date() await em.flush() updated = true diff --git a/src/services/player.service.ts b/src/services/player.service.ts index 00fab06d..bc2816b5 100644 --- a/src/services/player.service.ts +++ b/src/services/player.service.ts @@ -84,6 +84,10 @@ export default class PlayerService extends Service { const game = await em.getRepository(Game).findOne(req.ctx.state.game) const player = new Player(game) + if (req.ctx.state.continuityDate) { + player.createdAt = req.ctx.state.continuityDate + } + if (aliases) { for await (const alias of aliases) { if (await em.getRepository(PlayerAlias).count({ service: alias.service, identifier: alias.identifier }) > 0) { @@ -98,6 +102,10 @@ export default class PlayerService extends Service { const alias = new PlayerAlias() alias.service = item.service alias.identifier = item.identifier + if (req.ctx.state.continuityDate) { + alias.createdAt = req.ctx.state.continuityDate + } + return alias })) } diff --git a/tests/services/_api/game-feedback-api/post.test.ts b/tests/services/_api/game-feedback-api/post.test.ts index 06d8aa4c..a8857595 100644 --- a/tests/services/_api/game-feedback-api/post.test.ts +++ b/tests/services/_api/game-feedback-api/post.test.ts @@ -4,6 +4,7 @@ import { APIKeyScope } from '../../../../src/entities/api-key' import createAPIKeyAndToken from '../../../utils/createAPIKeyAndToken' import GameFeedbackCategoryFactory from '../../../fixtures/GameFeedbackCategoryFactory' import PlayerFactory from '../../../fixtures/PlayerFactory' +import { subHours } from 'date-fns' describe('Game feedback API service - post', () => { it('should create feedback if the scope is valid', async () => { @@ -76,4 +77,25 @@ describe('Game feedback API service - post', () => { expect(res.body).toStrictEqual({ message: 'Feedback category not found' }) }) + + it('should set the createdAt for the feedback to the continuity date', async () => { + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_GAME_FEEDBACK]) + + const feedbackCategory = await new GameFeedbackCategoryFactory(apiKey.game).one() + const player = await new PlayerFactory([apiKey.game]).one() + + await (global.em).persistAndFlush([feedbackCategory, player]) + + const continuityDate = subHours(new Date(), 1) + + const res = await request(global.app) + .post(`/v1/game-feedback/categories/${feedbackCategory.internalName}`) + .send({ comment: 'This is my comment' }) + .auth(token, { type: 'bearer' }) + .set('x-talo-alias', String(player.aliases[0].id)) + .set('x-talo-continuity-timestamp', String(continuityDate.getTime())) + .expect(200) + + expect(res.body.feedback.createdAt).toBe(continuityDate.toISOString()) + }) }) diff --git a/tests/services/_api/game-stat-api/put.test.ts b/tests/services/_api/game-stat-api/put.test.ts index 0379aaba..444e8b84 100644 --- a/tests/services/_api/game-stat-api/put.test.ts +++ b/tests/services/_api/game-stat-api/put.test.ts @@ -7,6 +7,7 @@ import GameStat from '../../../../src/entities/game-stat' import PlayerGameStatFactory from '../../../fixtures/PlayerGameStatFactory' import createAPIKeyAndToken from '../../../utils/createAPIKeyAndToken' import Game from '../../../../src/entities/game' +import { subHours } from 'date-fns' describe('Game stats API service - put', () => { const createStat = async (game: Game, props: Partial) => { @@ -228,4 +229,23 @@ describe('Game stats API service - put', () => { expect(res.body).toStrictEqual({ message: 'Stat not found' }) }) + + it('should set the createdAt of the player stat to the continuity date', async () => { + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_GAME_STATS]) + const stat = await createStat(apiKey.game, { maxValue: 999, maxChange: 99 }) + const player = await new PlayerFactory([apiKey.game]).one() + await (global.em).persistAndFlush(player) + + const continuityDate = subHours(new Date(), 1) + + const res = await request(global.app) + .put(`/v1/game-stats/${stat.internalName}`) + .send({ change: 10 }) + .auth(token, { type: 'bearer' }) + .set('x-talo-player', player.id) + .set('x-talo-continuity-timestamp', String(continuityDate.getTime())) + .expect(200) + + expect(res.body.playerStat.createdAt).toBe(continuityDate.toISOString()) + }) }) diff --git a/tests/services/_api/leaderboard-api/post.test.ts b/tests/services/_api/leaderboard-api/post.test.ts index 56e97c21..753c8cc8 100644 --- a/tests/services/_api/leaderboard-api/post.test.ts +++ b/tests/services/_api/leaderboard-api/post.test.ts @@ -220,4 +220,50 @@ describe('Leaderboard API service - post', () => { expect(res.body.entry.position).toBe(0) }) + + it('should set the createdAt for the entry to the continuity date', async () => { + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_LEADERBOARDS]) + const player = await new PlayerFactory([apiKey.game]).one() + const leaderboard = await new LeaderboardFactory([apiKey.game]).one() + await (global.em).persistAndFlush([player, leaderboard]) + + const continuityDate = subHours(new Date(), 1) + + const res = await request(global.app) + .post(`/v1/leaderboards/${leaderboard.internalName}/entries`) + .send({ score: 300 }) + .auth(token, { type: 'bearer' }) + .set('x-talo-alias', String(player.aliases[0].id)) + .set('x-talo-continuity-timestamp', String(continuityDate.getTime())) + .expect(200) + + expect(new Date(res.body.entry.createdAt).getHours()).toBe(continuityDate.getHours()) + }) + + it('should update an existing entry\'s created at to the continuity date for unique leaderboards', async () => { + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_LEADERBOARDS]) + const player = await new PlayerFactory([apiKey.game]).one() + const leaderboard = await new LeaderboardFactory([apiKey.game]).state(() => ({ unique: true, sortMode: LeaderboardSortMode.DESC })).one() + + const originalDate = subHours(new Date(), 2) + const continuityDate = subHours(new Date(), 1) + + const entry = await new LeaderboardEntryFactory(leaderboard, [player]).state(() => ({ + score: 100, + createdAt: originalDate, + playerAlias: player.aliases[0] + })).one() + + await (global.em).persistAndFlush([player, leaderboard, entry]) + + const res = await request(global.app) + .post(`/v1/leaderboards/${leaderboard.internalName}/entries`) + .send({ score: 300 }) + .auth(token, { type: 'bearer' }) + .set('x-talo-alias', String(player.aliases[0].id)) + .set('x-talo-continuity-timestamp', String(continuityDate.getTime())) + .expect(200) + + expect(new Date(res.body.entry.createdAt).getHours()).toBe(continuityDate.getHours()) + }) }) diff --git a/tests/services/_api/player-api/identify.test.ts b/tests/services/_api/player-api/identify.test.ts index 13a7dda7..018713b1 100644 --- a/tests/services/_api/player-api/identify.test.ts +++ b/tests/services/_api/player-api/identify.test.ts @@ -2,7 +2,7 @@ import { Collection, EntityManager } from '@mikro-orm/mysql' import request from 'supertest' import { APIKeyScope } from '../../../../src/entities/api-key' import PlayerFactory from '../../../fixtures/PlayerFactory' -import { isToday } from 'date-fns' +import { isToday, subHours } from 'date-fns' import PlayerGroupFactory from '../../../fixtures/PlayerGroupFactory' import PlayerGroupRule, { PlayerGroupRuleName, PlayerGroupRuleCastType } from '../../../../src/entities/player-group-rule' import PlayerProp from '../../../../src/entities/player-prop' @@ -124,4 +124,20 @@ describe('Player API service - identify', () => { expect(res.body).toStrictEqual({ message: 'Player not found: Talo aliases must be created using the /v1/players/auth API' }) }) + + it('should set the createdAt for the player and aliases to the continuity date', async () => { + const [, token] = await createAPIKeyAndToken([APIKeyScope.READ_PLAYERS, APIKeyScope.WRITE_PLAYERS]) + + const continuityDate = subHours(new Date(), 1) + + const res = await request(global.app) + .get('/v1/players/identify') + .query({ service: 'steam', identifier: 'bizboz' }) + .auth(token, { type: 'bearer' }) + .set('x-talo-continuity-timestamp', String(continuityDate.getTime())) + .expect(200) + + expect(res.body.alias.createdAt).toBe(continuityDate.toISOString()) + expect(res.body.alias.player.createdAt).toBe(continuityDate.toISOString()) + }) }) From e9ca6f7277cd2a83ebe103a7c70a0c595867d302 Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Mon, 26 Aug 2024 12:52:22 +0100 Subject: [PATCH 5/9] add WRITE_CONTINUITY_REQUESTS scope --- src/entities/api-key.ts | 1 + src/middlewares/continunity-middleware.ts | 15 ++++-- src/services/api/health-check-api.service.ts | 8 ++-- src/services/billing.service.ts | 2 +- src/services/player.service.ts | 8 ---- .../middlewares/continuity-middleware.test.ts | 47 +++++++++++++++++++ .../player-auth-middleware.test.ts | 2 +- .../_api/game-feedback-api/post.test.ts | 2 +- tests/services/_api/game-stat-api/put.test.ts | 2 +- .../_api/health-check-api/index.test.ts | 2 +- .../_api/leaderboard-api/post.test.ts | 4 +- .../services/_api/player-api/identify.test.ts | 18 +------ 12 files changed, 69 insertions(+), 42 deletions(-) create mode 100644 tests/middlewares/continuity-middleware.test.ts diff --git a/src/entities/api-key.ts b/src/entities/api-key.ts index ee34a6f3..70cdd0ed 100644 --- a/src/entities/api-key.ts +++ b/src/entities/api-key.ts @@ -3,6 +3,7 @@ import Game from './game' import User from './user' export enum APIKeyScope { + WRITE_CONTINUITY_REQUESTS = 'write:continuityRequests', READ_GAME_FEEDBACK = 'read:gameFeedback', WRITE_GAME_FEEDBACK = 'write:gameFeedback', READ_GAME_CONFIG = 'read:gameConfig', diff --git a/src/middlewares/continunity-middleware.ts b/src/middlewares/continunity-middleware.ts index d823ebbb..0007e394 100644 --- a/src/middlewares/continunity-middleware.ts +++ b/src/middlewares/continunity-middleware.ts @@ -1,13 +1,18 @@ import { isValid } from 'date-fns' import { Context, Next } from 'koa' +import { APIKeyScope } from '../entities/api-key' +import { isAPIRoute } from './route-middleware' +import checkScope from '../policies/checkScope' export default async (ctx: Context, next: Next): Promise => { - const header = ctx.headers['x-talo-continuity-timestamp'] + if (isAPIRoute(ctx) && checkScope(ctx.state.key, APIKeyScope.WRITE_CONTINUITY_REQUESTS)) { + const header = ctx.headers['x-talo-continuity-timestamp'] - if (header) { - const date = new Date(Number(header)) - if (isValid(date)) { - ctx.state.continuityDate = date + if (header) { + const date = new Date(Number(header)) + if (isValid(date)) { + ctx.state.continuityDate = date + } } } diff --git a/src/services/api/health-check-api.service.ts b/src/services/api/health-check-api.service.ts index 38739c9a..8d83bef0 100644 --- a/src/services/api/health-check-api.service.ts +++ b/src/services/api/health-check-api.service.ts @@ -1,4 +1,4 @@ -import { Response, Request, Routes } from 'koa-clay' +import { Response, Routes } from 'koa-clay' import APIService from './api-service' @Routes([ @@ -7,11 +7,9 @@ import APIService from './api-service' } ]) export default class HealthCheckAPIService extends APIService { - async index(req: Request): Promise { - console.log(req.ctx.state.continuityDate) - + async index(): Promise { return { - status: 200 + status: 204 } } } diff --git a/src/services/billing.service.ts b/src/services/billing.service.ts index 8a1a450f..869924a1 100644 --- a/src/services/billing.service.ts +++ b/src/services/billing.service.ts @@ -235,7 +235,7 @@ export default class BillingService extends Service { ) return { - status: 200 + status: 204 } } diff --git a/src/services/player.service.ts b/src/services/player.service.ts index bc2816b5..00fab06d 100644 --- a/src/services/player.service.ts +++ b/src/services/player.service.ts @@ -84,10 +84,6 @@ export default class PlayerService extends Service { const game = await em.getRepository(Game).findOne(req.ctx.state.game) const player = new Player(game) - if (req.ctx.state.continuityDate) { - player.createdAt = req.ctx.state.continuityDate - } - if (aliases) { for await (const alias of aliases) { if (await em.getRepository(PlayerAlias).count({ service: alias.service, identifier: alias.identifier }) > 0) { @@ -102,10 +98,6 @@ export default class PlayerService extends Service { const alias = new PlayerAlias() alias.service = item.service alias.identifier = item.identifier - if (req.ctx.state.continuityDate) { - alias.createdAt = req.ctx.state.continuityDate - } - return alias })) } diff --git a/tests/middlewares/continuity-middleware.test.ts b/tests/middlewares/continuity-middleware.test.ts new file mode 100644 index 00000000..8128e6da --- /dev/null +++ b/tests/middlewares/continuity-middleware.test.ts @@ -0,0 +1,47 @@ +import { EntityManager } from '@mikro-orm/mysql' +import request from 'supertest' +import createAPIKeyAndToken from '../utils/createAPIKeyAndToken' +import { APIKeyScope } from '../../src/entities/api-key' +import GameStatFactory from '../fixtures/GameStatFactory' +import PlayerFactory from '../fixtures/PlayerFactory' +import { subHours } from 'date-fns' + +describe('Continuity middleware', () => { + it('should not set the createdAt of the player stat to the continuity date if the write continuity requests scope isn\'t set', async () => { + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_GAME_STATS]) + const stat = await new GameStatFactory([apiKey.game]).state(() => ({ maxValue: 999, maxChange: 99 })).one() + const player = await new PlayerFactory([apiKey.game]).one() + await (global.em).persistAndFlush([stat, player]) + + const continuityDate = subHours(new Date(), 1) + + const res = await request(global.app) + .put(`/v1/game-stats/${stat.internalName}`) + .send({ change: 10 }) + .auth(token, { type: 'bearer' }) + .set('x-talo-player', player.id) + .set('x-talo-continuity-timestamp', String(continuityDate.getTime())) + .expect(200) + + expect(res.body.playerStat.createdAt).not.toBe(continuityDate.toISOString()) + }) + + it('should not set the createdAt of the player stat to the continuity date if the timestamp is invalid', async () => { + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_GAME_STATS, APIKeyScope.WRITE_CONTINUITY_REQUESTS]) + const stat = await new GameStatFactory([apiKey.game]).state(() => ({ maxValue: 999, maxChange: 99 })).one() + const player = await new PlayerFactory([apiKey.game]).one() + await (global.em).persistAndFlush([stat, player]) + + const continuityDate = subHours(new Date(), 1) + + const res = await request(global.app) + .put(`/v1/game-stats/${stat.internalName}`) + .send({ change: 10 }) + .auth(token, { type: 'bearer' }) + .set('x-talo-player', player.id) + .set('x-talo-continuity-timestamp', String(Math.ceil(continuityDate.getTime() / 1000))) + .expect(200) + + expect(res.body.playerStat.createdAt).not.toBe(continuityDate.toISOString()) + }) +}) diff --git a/tests/middlewares/player-auth-middleware.test.ts b/tests/middlewares/player-auth-middleware.test.ts index 6a2cff42..7afec81a 100644 --- a/tests/middlewares/player-auth-middleware.test.ts +++ b/tests/middlewares/player-auth-middleware.test.ts @@ -125,7 +125,7 @@ describe('Player auth middleware', () => { const stat = await new GameStatFactory([apiKey.game]).one() const player = await new PlayerFactory([apiKey.game]).withTaloAlias().one() - player.aliases.add(await new PlayerAliasFactory().one()) + player.aliases.add(await new PlayerAliasFactory(player).one()) await em.persistAndFlush([stat, player]) const sessionToken = await player.auth.createSession(player.aliases[0]) diff --git a/tests/services/_api/game-feedback-api/post.test.ts b/tests/services/_api/game-feedback-api/post.test.ts index a8857595..7b692657 100644 --- a/tests/services/_api/game-feedback-api/post.test.ts +++ b/tests/services/_api/game-feedback-api/post.test.ts @@ -79,7 +79,7 @@ describe('Game feedback API service - post', () => { }) it('should set the createdAt for the feedback to the continuity date', async () => { - const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_GAME_FEEDBACK]) + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_GAME_FEEDBACK, APIKeyScope.WRITE_CONTINUITY_REQUESTS]) const feedbackCategory = await new GameFeedbackCategoryFactory(apiKey.game).one() const player = await new PlayerFactory([apiKey.game]).one() diff --git a/tests/services/_api/game-stat-api/put.test.ts b/tests/services/_api/game-stat-api/put.test.ts index 444e8b84..f45b2262 100644 --- a/tests/services/_api/game-stat-api/put.test.ts +++ b/tests/services/_api/game-stat-api/put.test.ts @@ -231,7 +231,7 @@ describe('Game stats API service - put', () => { }) it('should set the createdAt of the player stat to the continuity date', async () => { - const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_GAME_STATS]) + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_GAME_STATS, APIKeyScope.WRITE_CONTINUITY_REQUESTS]) const stat = await createStat(apiKey.game, { maxValue: 999, maxChange: 99 }) const player = await new PlayerFactory([apiKey.game]).one() await (global.em).persistAndFlush(player) diff --git a/tests/services/_api/health-check-api/index.test.ts b/tests/services/_api/health-check-api/index.test.ts index 3deac630..55f86512 100644 --- a/tests/services/_api/health-check-api/index.test.ts +++ b/tests/services/_api/health-check-api/index.test.ts @@ -2,7 +2,7 @@ import request from 'supertest' import createAPIKeyAndToken from '../../../utils/createAPIKeyAndToken' describe('Health check API service - index', () => { - it('should return a 200', async () => { + it('should return a 204', async () => { const [, token] = await createAPIKeyAndToken([]) await request(global.app) diff --git a/tests/services/_api/leaderboard-api/post.test.ts b/tests/services/_api/leaderboard-api/post.test.ts index 753c8cc8..83cb8daa 100644 --- a/tests/services/_api/leaderboard-api/post.test.ts +++ b/tests/services/_api/leaderboard-api/post.test.ts @@ -222,7 +222,7 @@ describe('Leaderboard API service - post', () => { }) it('should set the createdAt for the entry to the continuity date', async () => { - const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_LEADERBOARDS]) + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_LEADERBOARDS, APIKeyScope.WRITE_CONTINUITY_REQUESTS]) const player = await new PlayerFactory([apiKey.game]).one() const leaderboard = await new LeaderboardFactory([apiKey.game]).one() await (global.em).persistAndFlush([player, leaderboard]) @@ -241,7 +241,7 @@ describe('Leaderboard API service - post', () => { }) it('should update an existing entry\'s created at to the continuity date for unique leaderboards', async () => { - const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_LEADERBOARDS]) + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.WRITE_LEADERBOARDS, APIKeyScope.WRITE_CONTINUITY_REQUESTS]) const player = await new PlayerFactory([apiKey.game]).one() const leaderboard = await new LeaderboardFactory([apiKey.game]).state(() => ({ unique: true, sortMode: LeaderboardSortMode.DESC })).one() diff --git a/tests/services/_api/player-api/identify.test.ts b/tests/services/_api/player-api/identify.test.ts index 018713b1..13a7dda7 100644 --- a/tests/services/_api/player-api/identify.test.ts +++ b/tests/services/_api/player-api/identify.test.ts @@ -2,7 +2,7 @@ import { Collection, EntityManager } from '@mikro-orm/mysql' import request from 'supertest' import { APIKeyScope } from '../../../../src/entities/api-key' import PlayerFactory from '../../../fixtures/PlayerFactory' -import { isToday, subHours } from 'date-fns' +import { isToday } from 'date-fns' import PlayerGroupFactory from '../../../fixtures/PlayerGroupFactory' import PlayerGroupRule, { PlayerGroupRuleName, PlayerGroupRuleCastType } from '../../../../src/entities/player-group-rule' import PlayerProp from '../../../../src/entities/player-prop' @@ -124,20 +124,4 @@ describe('Player API service - identify', () => { expect(res.body).toStrictEqual({ message: 'Player not found: Talo aliases must be created using the /v1/players/auth API' }) }) - - it('should set the createdAt for the player and aliases to the continuity date', async () => { - const [, token] = await createAPIKeyAndToken([APIKeyScope.READ_PLAYERS, APIKeyScope.WRITE_PLAYERS]) - - const continuityDate = subHours(new Date(), 1) - - const res = await request(global.app) - .get('/v1/players/identify') - .query({ service: 'steam', identifier: 'bizboz' }) - .auth(token, { type: 'bearer' }) - .set('x-talo-continuity-timestamp', String(continuityDate.getTime())) - .expect(200) - - expect(res.body.alias.createdAt).toBe(continuityDate.toISOString()) - expect(res.body.alias.player.createdAt).toBe(continuityDate.toISOString()) - }) }) From 2e4990fab0f4232636491563440396f8cb6332a3 Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:29:54 +0100 Subject: [PATCH 6/9] update mikro-orm to 6.3.6 --- package-lock.json | 62 +++++++++++++++++++++++------------------------ package.json | 10 ++++---- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/package-lock.json b/package-lock.json index f0b30bd3..6f2903d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,10 +12,10 @@ "@clickhouse/client": "^1.4.1", "@dinero.js/currencies": "^2.0.0-alpha.14", "@koa/cors": "^5.0.0", - "@mikro-orm/core": "^6.3.2", - "@mikro-orm/migrations": "^6.3.2", - "@mikro-orm/mysql": "^6.3.2", - "@mikro-orm/reflection": "^6.3.2", + "@mikro-orm/core": "^6.3.6", + "@mikro-orm/migrations": "^6.3.6", + "@mikro-orm/mysql": "^6.3.6", + "@mikro-orm/reflection": "^6.3.6", "@sendgrid/mail": "^7.6.2", "@sentry/node": "^7.47.0", "@sentry/utils": "^7.47.0", @@ -47,7 +47,7 @@ "uuid": "^9.0.0" }, "devDependencies": { - "@mikro-orm/cli": "^6.3.2", + "@mikro-orm/cli": "^6.3.6", "@stylistic/eslint-plugin": "^2.2.2", "@types/koa": "^2.13.5", "@types/koa-bodyparser": "^4.3.7", @@ -819,14 +819,14 @@ } }, "node_modules/@mikro-orm/cli": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/@mikro-orm/cli/-/cli-6.3.2.tgz", - "integrity": "sha512-4XJ8TiA0JAQS5AHF7muz+RrMKDdXCBg0x8E7mwgH/Bk2FBxK178NVtk6ov/CEBuLja8MiBgzGG3jh65sV0wUFQ==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@mikro-orm/cli/-/cli-6.3.6.tgz", + "integrity": "sha512-8NA5MeadqpdCk6bZh86xChFLiPNVSByxmPATjMhtsVi4ap89WQUQ3KwAE3uo2bfSQSk9N/1rUbw7EV0grGYIhQ==", "dev": true, "dependencies": { "@jercle/yargonaut": "1.1.5", - "@mikro-orm/core": "6.3.2", - "@mikro-orm/knex": "6.3.2", + "@mikro-orm/core": "6.3.6", + "@mikro-orm/knex": "6.3.6", "fs-extra": "11.2.0", "tsconfig-paths": "4.2.0", "yargs": "17.7.2" @@ -840,16 +840,16 @@ } }, "node_modules/@mikro-orm/core": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/@mikro-orm/core/-/core-6.3.2.tgz", - "integrity": "sha512-WgTO0InqjMW8nho4n/bk/fQNU1HYn6w4RtgYZ+e9wlFmnrEBj2pXTS68IV9DmUNYHAVNVVZl7/EcMlYaVzRkVg==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@mikro-orm/core/-/core-6.3.6.tgz", + "integrity": "sha512-zIcUT9Q5U4n0bFBybrUhLNZWaKv8OZIZwuukBNFQChy3Y5ziLwGpomsPWWGxuh/YZJbgj+bbYhmlMYy0hTyzeQ==", "dependencies": { "dataloader": "2.2.2", "dotenv": "16.4.5", "esprima": "4.0.1", "fs-extra": "11.2.0", "globby": "11.1.0", - "mikro-orm": "6.3.2", + "mikro-orm": "6.3.6", "reflect-metadata": "0.2.2" }, "engines": { @@ -860,9 +860,9 @@ } }, "node_modules/@mikro-orm/knex": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/@mikro-orm/knex/-/knex-6.3.2.tgz", - "integrity": "sha512-lESmITBJsTD3KIRFwQZnKaz2Va4DXcqiZoYYC4S32M+9TArxC8try2J7gmZWuQzGo/HszgBqfPFOxLyUF7ddiQ==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@mikro-orm/knex/-/knex-6.3.6.tgz", + "integrity": "sha512-mRQmrt7+Q8CbLE/UA+Mj0O2QSD98wHNc3OVFg1tMX8t9u75p+ob5oWUEutcUOU9cg3lm031jeZ7PPhUVgStGqQ==", "dependencies": { "fs-extra": "11.2.0", "knex": "3.1.0", @@ -890,11 +890,11 @@ } }, "node_modules/@mikro-orm/migrations": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/@mikro-orm/migrations/-/migrations-6.3.2.tgz", - "integrity": "sha512-nbzH6ZblpD04LTRJPgjCXhIeA2yLZshutrJnN06jU7iRPYkm0A/1VSCg0POaApgzyz+h+WxzK77FhUaCwJn9zg==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@mikro-orm/migrations/-/migrations-6.3.6.tgz", + "integrity": "sha512-mMdsHpW3Jg+ydm0aylnInDAG1ZKhdGGCzrnYASfB53DEvUe48CSdBQ4dt47uAzoHLfQzOjQfq4gWBNQPHZlIqg==", "dependencies": { - "@mikro-orm/knex": "6.3.2", + "@mikro-orm/knex": "6.3.6", "fs-extra": "11.2.0", "umzug": "3.8.1" }, @@ -906,11 +906,11 @@ } }, "node_modules/@mikro-orm/mysql": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/@mikro-orm/mysql/-/mysql-6.3.2.tgz", - "integrity": "sha512-cBzp43h9givZPp+/ZSR1qzU5gTdDEm/dacKx+SDZWYAd0J3ynhb+J7+WVPyMr918kjrSGjaVRfMzoc/wHxAWGQ==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@mikro-orm/mysql/-/mysql-6.3.6.tgz", + "integrity": "sha512-rG5RKBwCT9PQy+NsMHGWtYjfPP8mfisvfdpZIUnAFa7j5Ap+Uyz0UtIx2qxrsOojpiwfs1cn4hTROoYjATNj9Q==", "dependencies": { - "@mikro-orm/knex": "6.3.2", + "@mikro-orm/knex": "6.3.6", "mysql2": "3.11.0" }, "engines": { @@ -921,9 +921,9 @@ } }, "node_modules/@mikro-orm/reflection": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/@mikro-orm/reflection/-/reflection-6.3.2.tgz", - "integrity": "sha512-hrTa5owdrLssda6bGyOPKCpgxpxkqqajtAJ1MC3cEeA6I/P/Yd2ZnwzIsImrq9yU1io0rhQIAoi0737xuUz0MA==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@mikro-orm/reflection/-/reflection-6.3.6.tgz", + "integrity": "sha512-SO1AlfECE4HXgwzZr3lCvdcf6TdyyU/JTzQdCED+xkqanGmvVZ08kzZcsOGy+yLzOrstQNWnGajXXJn7P1xAag==", "dependencies": { "globby": "11.1.0", "ts-morph": "23.0.0" @@ -6331,9 +6331,9 @@ } }, "node_modules/mikro-orm": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/mikro-orm/-/mikro-orm-6.3.2.tgz", - "integrity": "sha512-5DcGDCasuW93dmPbFu+kd8sNO7MTcicYMW9RQH1rK/D77mKPxOmgsS14RAX+HuftbqWOBQXcTNZ+s9WUQ9UX4g==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/mikro-orm/-/mikro-orm-6.3.6.tgz", + "integrity": "sha512-1YzHYYiagqw6h5SqnrZ40XtudiqViENo5QlI0u9fRQHb0frU+UEZGHrSZWFeaqU4NHVSW3V6YRalk778RARzaw==", "engines": { "node": ">= 18.12.0" } diff --git a/package.json b/package.json index c993933c..fd7ed7ad 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "author": "Sleepy Studios", "license": "MIT", "devDependencies": { - "@mikro-orm/cli": "^6.3.2", + "@mikro-orm/cli": "^6.3.6", "@stylistic/eslint-plugin": "^2.2.2", "@types/koa": "^2.13.5", "@types/koa-bodyparser": "^4.3.7", @@ -50,10 +50,10 @@ "@clickhouse/client": "^1.4.1", "@dinero.js/currencies": "^2.0.0-alpha.14", "@koa/cors": "^5.0.0", - "@mikro-orm/core": "^6.3.2", - "@mikro-orm/migrations": "^6.3.2", - "@mikro-orm/mysql": "^6.3.2", - "@mikro-orm/reflection": "^6.3.2", + "@mikro-orm/core": "^6.3.6", + "@mikro-orm/migrations": "^6.3.6", + "@mikro-orm/mysql": "^6.3.6", + "@mikro-orm/reflection": "^6.3.6", "@sendgrid/mail": "^7.6.2", "@sentry/node": "^7.47.0", "@sentry/utils": "^7.47.0", From 99e0992dd85fb30d770ef11876317e0c04219f1e Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Tue, 27 Aug 2024 21:57:06 +0100 Subject: [PATCH 7/9] fix missing invitedByUser from invite --- src/services/public/invite-public.service.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/services/public/invite-public.service.ts b/src/services/public/invite-public.service.ts index 281f5294..f4c3736f 100644 --- a/src/services/public/invite-public.service.ts +++ b/src/services/public/invite-public.service.ts @@ -7,7 +7,12 @@ export default class InvitePublicService extends Service { const { id } = req.params const em: EntityManager = req.ctx.em - const invite = await em.getRepository(Invite).findOne({ token: id }, { populate: ['organisation'] }) + const invite = await em.getRepository(Invite).findOne({ + token: id + }, { + populate: ['organisation', 'invitedByUser'] + }) + if (!invite) req.ctx.throw(404, 'Invite not found') return { From f4b666ff89e140138011b603038687a37fd55143 Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Fri, 30 Aug 2024 23:23:32 +0100 Subject: [PATCH 8/9] mikro-orm 6.3.7 --- package-lock.json | 62 +++++++++++++++++++++++------------------------ package.json | 10 ++++---- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6f2903d1..9bce85ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,10 +12,10 @@ "@clickhouse/client": "^1.4.1", "@dinero.js/currencies": "^2.0.0-alpha.14", "@koa/cors": "^5.0.0", - "@mikro-orm/core": "^6.3.6", - "@mikro-orm/migrations": "^6.3.6", - "@mikro-orm/mysql": "^6.3.6", - "@mikro-orm/reflection": "^6.3.6", + "@mikro-orm/core": "^6.3.7", + "@mikro-orm/migrations": "^6.3.7", + "@mikro-orm/mysql": "^6.3.7", + "@mikro-orm/reflection": "^6.3.7", "@sendgrid/mail": "^7.6.2", "@sentry/node": "^7.47.0", "@sentry/utils": "^7.47.0", @@ -47,7 +47,7 @@ "uuid": "^9.0.0" }, "devDependencies": { - "@mikro-orm/cli": "^6.3.6", + "@mikro-orm/cli": "^6.3.7", "@stylistic/eslint-plugin": "^2.2.2", "@types/koa": "^2.13.5", "@types/koa-bodyparser": "^4.3.7", @@ -819,14 +819,14 @@ } }, "node_modules/@mikro-orm/cli": { - "version": "6.3.6", - "resolved": "https://registry.npmjs.org/@mikro-orm/cli/-/cli-6.3.6.tgz", - "integrity": "sha512-8NA5MeadqpdCk6bZh86xChFLiPNVSByxmPATjMhtsVi4ap89WQUQ3KwAE3uo2bfSQSk9N/1rUbw7EV0grGYIhQ==", + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/@mikro-orm/cli/-/cli-6.3.7.tgz", + "integrity": "sha512-jileNfqvYKxaFwQU3buUiky2uTltJ1auzPPvKxjROH7UfmWmBu0v740heXIV7vQo1uMXW5jqOepPx1vaKugxPQ==", "dev": true, "dependencies": { "@jercle/yargonaut": "1.1.5", - "@mikro-orm/core": "6.3.6", - "@mikro-orm/knex": "6.3.6", + "@mikro-orm/core": "6.3.7", + "@mikro-orm/knex": "6.3.7", "fs-extra": "11.2.0", "tsconfig-paths": "4.2.0", "yargs": "17.7.2" @@ -840,16 +840,16 @@ } }, "node_modules/@mikro-orm/core": { - "version": "6.3.6", - "resolved": "https://registry.npmjs.org/@mikro-orm/core/-/core-6.3.6.tgz", - "integrity": "sha512-zIcUT9Q5U4n0bFBybrUhLNZWaKv8OZIZwuukBNFQChy3Y5ziLwGpomsPWWGxuh/YZJbgj+bbYhmlMYy0hTyzeQ==", + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/@mikro-orm/core/-/core-6.3.7.tgz", + "integrity": "sha512-S8K257sTTUpnWCgtpJ4EI5kurSP6ha4Zwv1Moy9X33p4xH7JIpEHq5EVTTNZEaj/HbyX/nVRIqAm7ssUBcM1tA==", "dependencies": { "dataloader": "2.2.2", "dotenv": "16.4.5", "esprima": "4.0.1", "fs-extra": "11.2.0", "globby": "11.1.0", - "mikro-orm": "6.3.6", + "mikro-orm": "6.3.7", "reflect-metadata": "0.2.2" }, "engines": { @@ -860,9 +860,9 @@ } }, "node_modules/@mikro-orm/knex": { - "version": "6.3.6", - "resolved": "https://registry.npmjs.org/@mikro-orm/knex/-/knex-6.3.6.tgz", - "integrity": "sha512-mRQmrt7+Q8CbLE/UA+Mj0O2QSD98wHNc3OVFg1tMX8t9u75p+ob5oWUEutcUOU9cg3lm031jeZ7PPhUVgStGqQ==", + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/@mikro-orm/knex/-/knex-6.3.7.tgz", + "integrity": "sha512-V5wRl+3CM3OLlE8eMT9P/r7B5ZGs0Wjqco/zT7DEPx+j3ym3zk+vXYBVzq74xvKxgKy5F09hpTsvHC8/BhnpEQ==", "dependencies": { "fs-extra": "11.2.0", "knex": "3.1.0", @@ -890,11 +890,11 @@ } }, "node_modules/@mikro-orm/migrations": { - "version": "6.3.6", - "resolved": "https://registry.npmjs.org/@mikro-orm/migrations/-/migrations-6.3.6.tgz", - "integrity": "sha512-mMdsHpW3Jg+ydm0aylnInDAG1ZKhdGGCzrnYASfB53DEvUe48CSdBQ4dt47uAzoHLfQzOjQfq4gWBNQPHZlIqg==", + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/@mikro-orm/migrations/-/migrations-6.3.7.tgz", + "integrity": "sha512-QDTcn9yfCVwpfyl36VtT6jW2nZ7WlPu9ZENOLODw320eFuB7fPBFgXlOqTl+c04bnBoL6LahirhEQoSxEW80Vw==", "dependencies": { - "@mikro-orm/knex": "6.3.6", + "@mikro-orm/knex": "6.3.7", "fs-extra": "11.2.0", "umzug": "3.8.1" }, @@ -906,11 +906,11 @@ } }, "node_modules/@mikro-orm/mysql": { - "version": "6.3.6", - "resolved": "https://registry.npmjs.org/@mikro-orm/mysql/-/mysql-6.3.6.tgz", - "integrity": "sha512-rG5RKBwCT9PQy+NsMHGWtYjfPP8mfisvfdpZIUnAFa7j5Ap+Uyz0UtIx2qxrsOojpiwfs1cn4hTROoYjATNj9Q==", + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/@mikro-orm/mysql/-/mysql-6.3.7.tgz", + "integrity": "sha512-s+pq1GEDn1Iquk8NRLNYkUJw/O4ybd1FPq87p4e0taN6LHLY2U2RsREHdng0/HZwoQFZg0iB7EGMXTeOwRCpbw==", "dependencies": { - "@mikro-orm/knex": "6.3.6", + "@mikro-orm/knex": "6.3.7", "mysql2": "3.11.0" }, "engines": { @@ -921,9 +921,9 @@ } }, "node_modules/@mikro-orm/reflection": { - "version": "6.3.6", - "resolved": "https://registry.npmjs.org/@mikro-orm/reflection/-/reflection-6.3.6.tgz", - "integrity": "sha512-SO1AlfECE4HXgwzZr3lCvdcf6TdyyU/JTzQdCED+xkqanGmvVZ08kzZcsOGy+yLzOrstQNWnGajXXJn7P1xAag==", + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/@mikro-orm/reflection/-/reflection-6.3.7.tgz", + "integrity": "sha512-Y1KnxMpyZm89s/pXPQPcyqaebbn4c3PQvNnVWba93tpJYv2UueAptmHZyHhVELN9V6XwO6xUpzHbkotoYM1tXw==", "dependencies": { "globby": "11.1.0", "ts-morph": "23.0.0" @@ -6331,9 +6331,9 @@ } }, "node_modules/mikro-orm": { - "version": "6.3.6", - "resolved": "https://registry.npmjs.org/mikro-orm/-/mikro-orm-6.3.6.tgz", - "integrity": "sha512-1YzHYYiagqw6h5SqnrZ40XtudiqViENo5QlI0u9fRQHb0frU+UEZGHrSZWFeaqU4NHVSW3V6YRalk778RARzaw==", + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/mikro-orm/-/mikro-orm-6.3.7.tgz", + "integrity": "sha512-a4cvGnt2r4ViWm/r2VVTZ74X5o6YiSiJqVQXO5CpcPXk+A88hQr1zVX3fpqlv8em4H0rix9zFfeNW1m3LBtsYg==", "engines": { "node": ">= 18.12.0" } diff --git a/package.json b/package.json index fd7ed7ad..05047a89 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "author": "Sleepy Studios", "license": "MIT", "devDependencies": { - "@mikro-orm/cli": "^6.3.6", + "@mikro-orm/cli": "^6.3.7", "@stylistic/eslint-plugin": "^2.2.2", "@types/koa": "^2.13.5", "@types/koa-bodyparser": "^4.3.7", @@ -50,10 +50,10 @@ "@clickhouse/client": "^1.4.1", "@dinero.js/currencies": "^2.0.0-alpha.14", "@koa/cors": "^5.0.0", - "@mikro-orm/core": "^6.3.6", - "@mikro-orm/migrations": "^6.3.6", - "@mikro-orm/mysql": "^6.3.6", - "@mikro-orm/reflection": "^6.3.6", + "@mikro-orm/core": "^6.3.7", + "@mikro-orm/migrations": "^6.3.7", + "@mikro-orm/mysql": "^6.3.7", + "@mikro-orm/reflection": "^6.3.7", "@sendgrid/mail": "^7.6.2", "@sentry/node": "^7.47.0", "@sentry/utils": "^7.47.0", From 29b2abf8e93f12b5cc9c01d80de0e298981af03b Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Fri, 30 Aug 2024 23:23:49 +0100 Subject: [PATCH 9/9] 0.40.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9bce85ff..96c8fb83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "game-services", - "version": "0.39.0", + "version": "0.40.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "game-services", - "version": "0.39.0", + "version": "0.40.0", "license": "MIT", "dependencies": { "@clickhouse/client": "^1.4.1", diff --git a/package.json b/package.json index 05047a89..083ae522 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "game-services", - "version": "0.39.0", + "version": "0.40.0", "description": "", "main": "src/index.ts", "scripts": {