Skip to content

Commit

Permalink
Merge pull request #356 from TaloDev/develop
Browse files Browse the repository at this point in the history
Release 0.48.0
  • Loading branch information
tudddorrr authored Nov 2, 2024
2 parents 2f4978f + 28d9118 commit 7e72868
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 17 deletions.
2 changes: 1 addition & 1 deletion clickhouse/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM clickhouse/clickhouse-server:24.8-alpine
FROM clickhouse/clickhouse-server:24.10-alpine

RUN apk add --no-cache gettext

Expand Down
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "game-services",
"version": "0.47.1",
"version": "0.48.0",
"description": "",
"main": "src/index.ts",
"scripts": {
Expand Down
5 changes: 4 additions & 1 deletion src/entities/game-activity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ export enum GameActivityType {
GAME_FEEDBACK_CATEGORY_CREATED,
GAME_FEEDBACK_CATEGORY_UPDATED,
GAME_FEEDBACK_CATEGORY_DELETED,
API_KEY_UPDATED
API_KEY_UPDATED,
GAME_NAME_UPDATED
}

@Entity()
Expand Down Expand Up @@ -120,6 +121,8 @@ export default class GameActivity {
return `${this.user.username} deleted the feedback category ${this.extra.feedbackCategoryInternalName}`
case GameActivityType.API_KEY_UPDATED:
return `${this.user.username} updated an access key`
case GameActivityType.GAME_NAME_UPDATED:
return `${this.user.username} updated the game name`
default:
return ''
}
Expand Down
4 changes: 4 additions & 0 deletions src/entities/player-alias.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export default class PlayerAlias {
@Property({ default: false })
anonymised: boolean

@Property()
lastSeenAt: Date = new Date()

@Property()
createdAt: Date = new Date()

Expand All @@ -43,6 +46,7 @@ export default class PlayerAlias {
service: this.service,
identifier: this.identifier,
player,
lastSeenAt: this.lastSeenAt,
createdAt: this.createdAt,
updatedAt: this.updatedAt
}
Expand Down
3 changes: 3 additions & 0 deletions src/entities/player-prop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ export default class PlayerProp {
@Property()
value: string

@Property()
createdAt: Date = new Date()

constructor(player: Player, key: string, value: string) {
this.player = player
this.key = key
Expand Down
23 changes: 22 additions & 1 deletion src/migrations/.snapshot-gs_dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@
"mappedType": "string"
},
"members_visible": {
"name": "public",
"name": "members_visible",
"type": "tinyint(1)",
"unsigned": false,
"autoincrement": false,
Expand Down Expand Up @@ -1064,6 +1064,16 @@
"nullable": false,
"length": 255,
"mappedType": "string"
},
"created_at": {
"name": "created_at",
"type": "datetime",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"length": null,
"mappedType": "datetime"
}
},
"name": "player_prop",
Expand Down Expand Up @@ -1252,6 +1262,16 @@
"default": "false",
"mappedType": "boolean"
},
"last_seen_at": {
"name": "last_seen_at",
"type": "datetime",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"length": null,
"mappedType": "datetime"
},
"created_at": {
"name": "created_at",
"type": "datetime",
Expand Down Expand Up @@ -3781,6 +3801,7 @@
"nullable": false,
"length": null,
"enumItems": [
"read:playerGroups",
"write:continuityRequests",
"read:gameFeedback",
"write:gameFeedback",
Expand Down
18 changes: 18 additions & 0 deletions src/migrations/20241101233908AddPlayerPropCreatedAtColumn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Migration } from '@mikro-orm/migrations'

export class AddPlayerPropCreatedAtColumn extends Migration {

override async up(): Promise<void> {
this.addSql('alter table `player_prop` add `created_at` datetime not null default CURRENT_TIMESTAMP;')
this.addSql('update `player_prop` set `created_at` = (select `updated_at` from `player` where `player`.`id` = `player_prop`.`player_id`);')

this.addSql('alter table `apikey` modify `scopes` text not null;')
}

override async down(): Promise<void> {
this.addSql('alter table `player_prop` drop column `created_at`;')

this.addSql('alter table `apikey` modify `scopes` text not null;')
}

}
14 changes: 14 additions & 0 deletions src/migrations/20241102004938AddPlayerAliasLastSeenAtColumn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Migration } from '@mikro-orm/migrations'

export class AddPlayerAliasLastSeenAtColumn extends Migration {

override async up(): Promise<void> {
this.addSql('alter table `player_alias` add `last_seen_at` datetime not null default CURRENT_TIMESTAMP;')
this.addSql('update `player_alias` set `last_seen_at` = `updated_at`;')
}

override async down(): Promise<void> {
this.addSql('alter table `player_alias` drop column `last_seen_at`;')
}

}
10 changes: 10 additions & 0 deletions src/migrations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import { AddPlayerAliasAnonymisedColumn } from './20240920121232AddPlayerAliasAn
import { AddLeaderboardEntryPropsColumn } from './20240922222426AddLeaderboardEntryPropsColumn'
import { CreateUserPinnedGroupsTable } from './20241001194252CreateUserPinnedGroupsTable'
import { AddPlayerGroupMembersVisibleColumn } from './20241014202844AddPlayerGroupMembersVisibleColumn'
import { AddPlayerPropCreatedAtColumn } from './20241101233908AddPlayerPropCreatedAtColumn'
import { AddPlayerAliasLastSeenAtColumn } from './20241102004938AddPlayerAliasLastSeenAtColumn'

export default [
{
Expand Down Expand Up @@ -164,5 +166,13 @@ export default [
{
name: 'AddPlayerGroupMembersVisibleColumn',
class: AddPlayerGroupMembersVisibleColumn
},
{
name: 'AddPlayerPropCreatedAtColumn',
class: AddPlayerPropCreatedAtColumn
},
{
name: 'AddPlayerAliasLastSeenAtColumn',
class: AddPlayerAliasLastSeenAtColumn
}
]
7 changes: 4 additions & 3 deletions src/services/api/player-api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export default class PlayerAPIService extends APIService {
}
}

alias.player.lastSeenAt = new Date()
alias.lastSeenAt = alias.player.lastSeenAt = new Date()
await em.flush()

return {
Expand Down Expand Up @@ -189,9 +189,10 @@ export default class PlayerAPIService extends APIService {
...player1.props.getItems()
], (a, b) => a.key === b.key)

player1.setProps(mergedProps)
player1.aliases.add(player2.aliases)
player1.setProps(mergedProps.map((prop) => ({ key: prop.key, value: prop.value })))
player2.aliases.getItems().forEach((alias) => alias.player = player1)
player2.setProps([])
await em.flush()

const saves = await em.getRepository(GameSave).find({ player: player2 })
saves.forEach((save) => save.player = player1)
Expand Down
18 changes: 17 additions & 1 deletion src/services/game.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,27 @@ export default class GameService extends Service {

@HasPermission(GamePolicy, 'patch')
async patch(req: Request): Promise<Response> {
const { props } = req.body
const { name, props } = req.body
const em: EntityManager = req.ctx.em

const game: Game = req.ctx.state.game

if (name) {
const prevName = game.name
game.name = name

createGameActivity(em, {
user: req.ctx.state.user,
game,
type: GameActivityType.GAME_NAME_UPDATED,
extra: {
display: {
'Previous name': prevName
}
}
})
}

if (props) {
if (props.some((prop) => prop.key.startsWith('META_'))) {
req.ctx.throw(400, 'Prop keys starting with \'META_\' are reserved for internal systems, please use another key name')
Expand Down
7 changes: 6 additions & 1 deletion src/services/player-group.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import createGameActivity from '../lib/logging/createGameActivity'
import PlayerGroupPolicy from '../policies/player-group.policy'
import getUserFromToken from '../lib/auth/getUserFromToken'
import UserPinnedGroup from '../entities/user-pinned-group'
import { devDataPlayerFilter } from '../middlewares/dev-data-middleware'

@Routes([
{
Expand Down Expand Up @@ -229,7 +230,11 @@ export default class PlayerGroupService extends Service {
group.rules = this.buildRulesFromData(JSON.parse(decodeURI(rules)))
group.ruleMode = ruleMode as RuleMode

const count = await group.getQuery(em).getCount()
const query = group.getQuery(em)
if (!req.ctx.state.includeDevData) {
query.andWhere(devDataPlayerFilter(em))
}
const count = await query.getCount()

return {
status: 200,
Expand Down
18 changes: 15 additions & 3 deletions tests/services/_api/player-api/identify.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ 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, subDays } 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'
import { RuleMode } from '../../../../src/entities/player-group'
import createAPIKeyAndToken from '../../../utils/createAPIKeyAndToken'
import PlayerAlias from '../../../../src/entities/player-alias'
import PlayerAliasFactory from '../../../fixtures/PlayerAliasFactory'
import casual from 'casual'

describe('Player API service - identify', () => {
it('should identify a player', async () => {
Expand All @@ -27,7 +30,15 @@ describe('Player API service - identify', () => {

it('should update the lastSeenAt when a player identifies', async () => {
const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.READ_PLAYERS])
const player = await new PlayerFactory([apiKey.game]).notSeenToday().one()
const player = await new PlayerFactory([apiKey.game]).notSeenToday().state(async (player) => {
const alias = await new PlayerAliasFactory(player).state(() => ({
lastSeenAt: subDays(new Date(), casual.integer(1, 99))
})).one()

return {
aliases: new Collection<PlayerAlias>(player, [alias])
}
}).one()
await (<EntityManager>global.em).persistAndFlush(player)

await request(global.app)
Expand All @@ -36,8 +47,9 @@ describe('Player API service - identify', () => {
.auth(token, { type: 'bearer' })
.expect(200)

await (<EntityManager>global.em).refresh(player)
await (<EntityManager>global.em).refresh(player, { populate: ['aliases'] })
expect(isToday(new Date(player.lastSeenAt))).toBe(true)
expect(isToday(new Date(player.aliases[0].lastSeenAt))).toBe(true)
})

it('should not identify a player if the scope is missing', async () => {
Expand Down
26 changes: 26 additions & 0 deletions tests/services/game/patch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,30 @@ describe('Game service - patch', () => {
message: 'Prop keys starting with \'META_\' are reserved for internal systems, please use another key name'
})
})

it('should update game names', async () => {
const [organisation, game] = await createOrganisationAndGame()
const [token] = await createUserAndToken({ type: UserType.ADMIN }, organisation)

const res = await request(global.app)
.patch(`/games/${game.id}`)
.send({
name: 'New game name'
})
.auth(token, { type: 'bearer' })
.expect(200)

expect(res.body.game.name).toBe('New game name')

const activity = await (<EntityManager>global.em).getRepository(GameActivity).findOne({
type: GameActivityType.GAME_NAME_UPDATED,
game,
extra: {
display: {
'Previous name': game.name
}
}
})
expect(activity).not.toBeNull()
})
})
Loading

0 comments on commit 7e72868

Please sign in to comment.