From 9a5e75cd55c0dca1fe07fc95fa6dfda067956875 Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Fri, 4 Oct 2024 20:52:14 +0100 Subject: [PATCH 1/9] latest mikro-orm --- package-lock.json | 148 ++++++++++++++++++++++++---------------------- package.json | 10 ++-- 2 files changed, 82 insertions(+), 76 deletions(-) diff --git a/package-lock.json b/package-lock.json index ddfed8e7..16fa6d18 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.9", - "@mikro-orm/migrations": "^6.3.9", - "@mikro-orm/mysql": "^6.3.9", - "@mikro-orm/reflection": "^6.3.9", + "@mikro-orm/core": "^6.3.12", + "@mikro-orm/migrations": "^6.3.12", + "@mikro-orm/mysql": "^6.3.12", + "@mikro-orm/reflection": "^6.3.12", "@sendgrid/mail": "^8.1.3", "@sentry/node": "^7.47.0", "@sentry/utils": "^7.47.0", @@ -44,7 +44,7 @@ "uuid": "^9.0.0" }, "devDependencies": { - "@mikro-orm/cli": "^6.3.9", + "@mikro-orm/cli": "^6.3.12", "@stylistic/eslint-plugin": "^2.2.2", "@types/koa": "^2.13.5", "@types/koa-bodyparser": "^4.3.7", @@ -818,14 +818,14 @@ } }, "node_modules/@mikro-orm/cli": { - "version": "6.3.9", - "resolved": "https://registry.npmjs.org/@mikro-orm/cli/-/cli-6.3.9.tgz", - "integrity": "sha512-skvqm4lV5L/MDDqXn8jeureMSdIT/7OHqSvFiYSFNbLweKp/gOarCdVSSC+fmL3sEiUoE1CCCc6Eo4lpia2xDw==", + "version": "6.3.12", + "resolved": "https://registry.npmjs.org/@mikro-orm/cli/-/cli-6.3.12.tgz", + "integrity": "sha512-r2dhhAvXr3rbX/zW/pvkZ6Tuj/ukgW148ZU+HhkcQxFdpGHR2X9pxHgNG3Z1qfx38/AA87jvdfox+f/NaKtLQg==", "dev": true, "dependencies": { "@jercle/yargonaut": "1.1.5", - "@mikro-orm/core": "6.3.9", - "@mikro-orm/knex": "6.3.9", + "@mikro-orm/core": "6.3.12", + "@mikro-orm/knex": "6.3.12", "fs-extra": "11.2.0", "tsconfig-paths": "4.2.0", "yargs": "17.7.2" @@ -839,16 +839,16 @@ } }, "node_modules/@mikro-orm/core": { - "version": "6.3.9", - "resolved": "https://registry.npmjs.org/@mikro-orm/core/-/core-6.3.9.tgz", - "integrity": "sha512-RKJ8jQWd+xOaUq02zhNbw/yhguFDopMayefsirOBPAXBhRyndqZOB86ZBetDWYcOhJDI9VCqufZldrvC59r6eQ==", + "version": "6.3.12", + "resolved": "https://registry.npmjs.org/@mikro-orm/core/-/core-6.3.12.tgz", + "integrity": "sha512-CkUDS9Ghs4vLBbpVTvtJalTVyvQ82Lwow8K8GhJTNJcXYDWtFT4231zLVveb6mTB5ayM3rof19pRsIKEb2SJvw==", "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.9", + "mikro-orm": "6.3.12", "reflect-metadata": "0.2.2" }, "engines": { @@ -859,9 +859,9 @@ } }, "node_modules/@mikro-orm/knex": { - "version": "6.3.9", - "resolved": "https://registry.npmjs.org/@mikro-orm/knex/-/knex-6.3.9.tgz", - "integrity": "sha512-KnyZyoH/RdT4Te4ZcjxnROrOUDTV0HQLl+RijjsJSIsqaQzF485qio03CowDnOmMWSiUjFQlBRxKRaKdN3Bhqg==", + "version": "6.3.12", + "resolved": "https://registry.npmjs.org/@mikro-orm/knex/-/knex-6.3.12.tgz", + "integrity": "sha512-TQ8lU+jwsZ0FWEnBvgICgyVOx4g0j8Vm7kOKC+fJDdXPpBz3N4JYu+y30NQ0fIiPEHBzOpvusCV42FxhSQ/DVQ==", "dependencies": { "fs-extra": "11.2.0", "knex": "3.1.0", @@ -889,13 +889,13 @@ } }, "node_modules/@mikro-orm/migrations": { - "version": "6.3.9", - "resolved": "https://registry.npmjs.org/@mikro-orm/migrations/-/migrations-6.3.9.tgz", - "integrity": "sha512-BUfuQbx4JHDTV4UylQDtA3qnL9exm2DcujwX9h3TLZnmPT4PURfMBobonBWagvB7TnDgvhHHcWdjRvm8uxZ1oQ==", + "version": "6.3.12", + "resolved": "https://registry.npmjs.org/@mikro-orm/migrations/-/migrations-6.3.12.tgz", + "integrity": "sha512-ASbfQbL8KVHc6LCmUZGsbFPL+t8x7BZiMQIn12YSq9eLJw9oy1a0Qd5afQYEP4llVMFgkn2ROM9dsSg+KIBUjw==", "dependencies": { - "@mikro-orm/knex": "6.3.9", + "@mikro-orm/knex": "6.3.12", "fs-extra": "11.2.0", - "umzug": "3.8.1" + "umzug": "3.8.2" }, "engines": { "node": ">= 18.12.0" @@ -905,12 +905,12 @@ } }, "node_modules/@mikro-orm/mysql": { - "version": "6.3.9", - "resolved": "https://registry.npmjs.org/@mikro-orm/mysql/-/mysql-6.3.9.tgz", - "integrity": "sha512-5emI4E03maJUy+8r+bHIRhU7V9+bFbxQf3xRgk5u4ONYFlK5WFt1xOinqGFwPNtlCsQXel4jDlhYmw5mGD11GQ==", + "version": "6.3.12", + "resolved": "https://registry.npmjs.org/@mikro-orm/mysql/-/mysql-6.3.12.tgz", + "integrity": "sha512-eiJF6gVQ4KngzTaZHJKngFTjj0taO9eypRJfLRElmO77E/iMU5dqnrGLtKv9oGoP21PELQCm+hbPjfmL1lFmzw==", "dependencies": { - "@mikro-orm/knex": "6.3.9", - "mysql2": "3.11.0" + "@mikro-orm/knex": "6.3.12", + "mysql2": "3.11.3" }, "engines": { "node": ">= 18.12.0" @@ -920,9 +920,9 @@ } }, "node_modules/@mikro-orm/reflection": { - "version": "6.3.9", - "resolved": "https://registry.npmjs.org/@mikro-orm/reflection/-/reflection-6.3.9.tgz", - "integrity": "sha512-Tj7fJY3NMBVfiRr2vNOyFtEzR9Nk05osPpwDfDXHVd2wDtVhkR5kpgvlRAUOLsfkcX5FYTfmGKrTEqqxH0OCLA==", + "version": "6.3.12", + "resolved": "https://registry.npmjs.org/@mikro-orm/reflection/-/reflection-6.3.12.tgz", + "integrity": "sha512-EHVMRrX5ycEuoo67TYzS4L2Iz+zPW49d1lh8eVxNdfHLd3QgM35YUEPvVfs5LTmnG3FJPx3qXHXeOapuWZ76wA==", "dependencies": { "globby": "11.1.0", "ts-morph": "23.0.0" @@ -1238,9 +1238,9 @@ ] }, "node_modules/@rushstack/node-core-library": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.5.1.tgz", - "integrity": "sha512-ZutW56qIzH8xIOlfyaLQJFx+8IBqdbVCZdnj+XT1MorQ1JqqxHse8vbCpEM+2MjsrqcbxcgDIbfggB1ZSQ2A3g==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.9.0.tgz", + "integrity": "sha512-MMsshEWkTbXqxqFxD4gcIUWQOCeBChlGczdZbHfqmNZQFLHB3yWxDFSMHFUdu2/OB9NUk7Awn5qRL+rws4HQNg==", "dependencies": { "ajv": "~8.13.0", "ajv-draft-04": "~1.0.0", @@ -1323,11 +1323,11 @@ } }, "node_modules/@rushstack/terminal": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.13.3.tgz", - "integrity": "sha512-fc3zjXOw8E0pXS5t9vTiIPx9gHA0fIdTXsu9mT4WbH+P3mYvnrX0iAQ5a6NvyK1+CqYWBTw/wVNx7SDJkI+WYQ==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.14.2.tgz", + "integrity": "sha512-2fC1wqu1VCExKC0/L+0noVcFQEXEnoBOtCIex1TOjBzEDWcw8KzJjjj7aTP6mLxepG0XIyn9OufeFb6SFsa+sg==", "dependencies": { - "@rushstack/node-core-library": "5.5.1", + "@rushstack/node-core-library": "5.9.0", "supports-color": "~8.1.1" }, "peerDependencies": { @@ -1354,11 +1354,11 @@ } }, "node_modules/@rushstack/ts-command-line": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.22.3.tgz", - "integrity": "sha512-edMpWB3QhFFZ4KtSzS8WNjBgR4PXPPOVrOHMbb7kNpmQ1UFS9HdVtjCXg1H5fG+xYAbeE+TMPcVPUyX2p84STA==", + "version": "4.22.8", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.22.8.tgz", + "integrity": "sha512-XbFjOoV7qZHJnSuFUHv0pKaFA4ixyCuki+xMjsMfDwfvQjs5MYG0IK5COal3tRnG7KCDe2l/G+9LrzYE/RJhgg==", "dependencies": { - "@rushstack/terminal": "0.13.3", + "@rushstack/terminal": "0.14.2", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" @@ -2787,9 +2787,9 @@ "license": "MIT" }, "node_modules/aws-ssl-profiles": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.1.tgz", - "integrity": "sha512-+H+kuK34PfMaI9PNU/NSjBKL5hh/KDM9J72kwYeYEm0A8B1AC4fuCy3qsjnA7lxklgyXsB68yn8Z2xoZEjgwCQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", "engines": { "node": ">= 6.0.0" } @@ -4185,9 +4185,9 @@ "dev": true }, "node_modules/fast-uri": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", + "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==" }, "node_modules/fastq": { "version": "1.16.0", @@ -5072,9 +5072,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", - "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dependencies": { "hasown": "^2.0.2" }, @@ -6104,6 +6104,20 @@ "node": ">=10" } }, + "node_modules/lru.min": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.1.tgz", + "integrity": "sha512-FbAj6lXil6t8z4z3j0E5mfRlPzxkySotzUHwRXjlpRh10vc6AI6WN62ehZj82VG7M20rqogJ0GLwar2Xa05a8Q==", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, "node_modules/luxon": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz", @@ -6215,9 +6229,9 @@ } }, "node_modules/mikro-orm": { - "version": "6.3.9", - "resolved": "https://registry.npmjs.org/mikro-orm/-/mikro-orm-6.3.9.tgz", - "integrity": "sha512-xI8pbOTEBbvnnqdrA+PwcEgB4kixdxUs4zh3mw432aJhoF7+yI65vV9ANKjeZDXoROYT3U3UH+jzAbYb051KPg==", + "version": "6.3.12", + "resolved": "https://registry.npmjs.org/mikro-orm/-/mikro-orm-6.3.12.tgz", + "integrity": "sha512-CMLaxhq7EANGI0JD3EEhyafGf3fZh5ATvG1kNP/20DBarZBYSsp2GGzxhEENs0SCOVy5+dWWRL8vSuke/hIKEw==", "engines": { "node": ">= 18.12.0" } @@ -6390,16 +6404,16 @@ } }, "node_modules/mysql2": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.11.0.tgz", - "integrity": "sha512-J9phbsXGvTOcRVPR95YedzVSxJecpW5A5+cQ57rhHIFXteTP10HCs+VBjS7DHIKfEaI1zQ5tlVrquCd64A6YvA==", + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.11.3.tgz", + "integrity": "sha512-Qpu2ADfbKzyLdwC/5d4W7+5Yz7yBzCU05YWt5npWzACST37wJsB23wgOSo00qi043urkiRwXtEvJc9UnuLX/MQ==", "dependencies": { "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", "generate-function": "^2.3.1", "iconv-lite": "^0.6.3", "long": "^5.2.1", - "lru-cache": "^8.0.0", + "lru.min": "^1.0.0", "named-placeholders": "^1.1.3", "seq-queue": "^0.0.5", "sqlstring": "^2.3.2" @@ -6408,14 +6422,6 @@ "node": ">= 8.0" } }, - "node_modules/mysql2/node_modules/lru-cache": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", - "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", - "engines": { - "node": ">=16.14" - } - }, "node_modules/named-placeholders": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", @@ -8282,9 +8288,9 @@ } }, "node_modules/umzug": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/umzug/-/umzug-3.8.1.tgz", - "integrity": "sha512-k0HjOc3b/s8vH24BUTvnaFiKhfWI9UQAGpqHDG+3866CGlBTB83Xs5wZ1io1mwYLj/GHvQ34AxKhbpYnWtkRJg==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-3.8.2.tgz", + "integrity": "sha512-BEWEF8OJjTYVC56GjELeHl/1XjFejrD7aHzn+HldRJTx+pL1siBrKHZC8n4K/xL3bEzVA9o++qD1tK2CpZu4KA==", "dependencies": { "@rushstack/ts-command-line": "^4.12.2", "emittery": "^0.13.0", @@ -8297,9 +8303,9 @@ } }, "node_modules/umzug/node_modules/type-fest": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.23.0.tgz", - "integrity": "sha512-ZiBujro2ohr5+Z/hZWHESLz3g08BBdrdLMieYFULJO+tWc437sn8kQsWLJoZErY8alNhxre9K4p3GURAG11n+w==", + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "engines": { "node": ">=16" }, diff --git a/package.json b/package.json index 4dd2701a..64e7918e 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "author": "Sleepy Studios", "license": "MIT", "devDependencies": { - "@mikro-orm/cli": "^6.3.9", + "@mikro-orm/cli": "^6.3.12", "@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.9", - "@mikro-orm/migrations": "^6.3.9", - "@mikro-orm/mysql": "^6.3.9", - "@mikro-orm/reflection": "^6.3.9", + "@mikro-orm/core": "^6.3.12", + "@mikro-orm/migrations": "^6.3.12", + "@mikro-orm/mysql": "^6.3.12", + "@mikro-orm/reflection": "^6.3.12", "@sendgrid/mail": "^8.1.3", "@sentry/node": "^7.47.0", "@sentry/utils": "^7.47.0", From 7b39c39777b4dde2877152966ca602653a154cac Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Tue, 8 Oct 2024 18:00:02 +0100 Subject: [PATCH 2/9] latest mikro-orm --- 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 16fa6d18..3e765fd6 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.12", - "@mikro-orm/migrations": "^6.3.12", - "@mikro-orm/mysql": "^6.3.12", - "@mikro-orm/reflection": "^6.3.12", + "@mikro-orm/core": "^6.3.13", + "@mikro-orm/migrations": "^6.3.13", + "@mikro-orm/mysql": "^6.3.13", + "@mikro-orm/reflection": "^6.3.13", "@sendgrid/mail": "^8.1.3", "@sentry/node": "^7.47.0", "@sentry/utils": "^7.47.0", @@ -44,7 +44,7 @@ "uuid": "^9.0.0" }, "devDependencies": { - "@mikro-orm/cli": "^6.3.12", + "@mikro-orm/cli": "^6.3.13", "@stylistic/eslint-plugin": "^2.2.2", "@types/koa": "^2.13.5", "@types/koa-bodyparser": "^4.3.7", @@ -818,14 +818,14 @@ } }, "node_modules/@mikro-orm/cli": { - "version": "6.3.12", - "resolved": "https://registry.npmjs.org/@mikro-orm/cli/-/cli-6.3.12.tgz", - "integrity": "sha512-r2dhhAvXr3rbX/zW/pvkZ6Tuj/ukgW148ZU+HhkcQxFdpGHR2X9pxHgNG3Z1qfx38/AA87jvdfox+f/NaKtLQg==", + "version": "6.3.13", + "resolved": "https://registry.npmjs.org/@mikro-orm/cli/-/cli-6.3.13.tgz", + "integrity": "sha512-6ubnNi7waCyNUsed8nFGeJ9HTg1CfoFnd01Wj0c7Bcb0Ktq0+5lvbS7oXUOKhrTF2zrIOEdRKknzza9OGRWW8A==", "dev": true, "dependencies": { "@jercle/yargonaut": "1.1.5", - "@mikro-orm/core": "6.3.12", - "@mikro-orm/knex": "6.3.12", + "@mikro-orm/core": "6.3.13", + "@mikro-orm/knex": "6.3.13", "fs-extra": "11.2.0", "tsconfig-paths": "4.2.0", "yargs": "17.7.2" @@ -839,16 +839,16 @@ } }, "node_modules/@mikro-orm/core": { - "version": "6.3.12", - "resolved": "https://registry.npmjs.org/@mikro-orm/core/-/core-6.3.12.tgz", - "integrity": "sha512-CkUDS9Ghs4vLBbpVTvtJalTVyvQ82Lwow8K8GhJTNJcXYDWtFT4231zLVveb6mTB5ayM3rof19pRsIKEb2SJvw==", + "version": "6.3.13", + "resolved": "https://registry.npmjs.org/@mikro-orm/core/-/core-6.3.13.tgz", + "integrity": "sha512-gNvk/98Xe283+Yn4CFxNNJmx1iXT8gRfDn4agjFUa4pI9pVw+idkxOljXuLlvoW44ybiwji8qagaoY+tmD0BTQ==", "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.12", + "mikro-orm": "6.3.13", "reflect-metadata": "0.2.2" }, "engines": { @@ -859,9 +859,9 @@ } }, "node_modules/@mikro-orm/knex": { - "version": "6.3.12", - "resolved": "https://registry.npmjs.org/@mikro-orm/knex/-/knex-6.3.12.tgz", - "integrity": "sha512-TQ8lU+jwsZ0FWEnBvgICgyVOx4g0j8Vm7kOKC+fJDdXPpBz3N4JYu+y30NQ0fIiPEHBzOpvusCV42FxhSQ/DVQ==", + "version": "6.3.13", + "resolved": "https://registry.npmjs.org/@mikro-orm/knex/-/knex-6.3.13.tgz", + "integrity": "sha512-+ws7bEFbgw2fLYry9KZJ2pQpGgzCsoke/sFn0Dn8vNznqdq5ktJMGj5kxBRsLhzGQ4zS1wjgn0JJELqXVtPX5g==", "dependencies": { "fs-extra": "11.2.0", "knex": "3.1.0", @@ -889,11 +889,11 @@ } }, "node_modules/@mikro-orm/migrations": { - "version": "6.3.12", - "resolved": "https://registry.npmjs.org/@mikro-orm/migrations/-/migrations-6.3.12.tgz", - "integrity": "sha512-ASbfQbL8KVHc6LCmUZGsbFPL+t8x7BZiMQIn12YSq9eLJw9oy1a0Qd5afQYEP4llVMFgkn2ROM9dsSg+KIBUjw==", + "version": "6.3.13", + "resolved": "https://registry.npmjs.org/@mikro-orm/migrations/-/migrations-6.3.13.tgz", + "integrity": "sha512-MipfBYT93HK4Xf4GCRNjqx0+8CbBBiA4dwzORawDSjg5Vmlaa2adxKIZpH71NDF/RQVPz8ody0Yp1CwrrlbOlA==", "dependencies": { - "@mikro-orm/knex": "6.3.12", + "@mikro-orm/knex": "6.3.13", "fs-extra": "11.2.0", "umzug": "3.8.2" }, @@ -905,11 +905,11 @@ } }, "node_modules/@mikro-orm/mysql": { - "version": "6.3.12", - "resolved": "https://registry.npmjs.org/@mikro-orm/mysql/-/mysql-6.3.12.tgz", - "integrity": "sha512-eiJF6gVQ4KngzTaZHJKngFTjj0taO9eypRJfLRElmO77E/iMU5dqnrGLtKv9oGoP21PELQCm+hbPjfmL1lFmzw==", + "version": "6.3.13", + "resolved": "https://registry.npmjs.org/@mikro-orm/mysql/-/mysql-6.3.13.tgz", + "integrity": "sha512-SU6PTUp21r050M2hqi102kV+PGVNjkBfRd1svSI6B6aDEcyvWioygaBnTojchJ4cdADDwQFrTqP88dvI8Mv6LQ==", "dependencies": { - "@mikro-orm/knex": "6.3.12", + "@mikro-orm/knex": "6.3.13", "mysql2": "3.11.3" }, "engines": { @@ -920,9 +920,9 @@ } }, "node_modules/@mikro-orm/reflection": { - "version": "6.3.12", - "resolved": "https://registry.npmjs.org/@mikro-orm/reflection/-/reflection-6.3.12.tgz", - "integrity": "sha512-EHVMRrX5ycEuoo67TYzS4L2Iz+zPW49d1lh8eVxNdfHLd3QgM35YUEPvVfs5LTmnG3FJPx3qXHXeOapuWZ76wA==", + "version": "6.3.13", + "resolved": "https://registry.npmjs.org/@mikro-orm/reflection/-/reflection-6.3.13.tgz", + "integrity": "sha512-fNsMnQRoSMg5IoQjAgZqFm8ewnXrD9/BvdHoyDP62TzbbaNd5wm0M9UL4hBjFYiy706m0iLPlC7ZAgrTOzbSCA==", "dependencies": { "globby": "11.1.0", "ts-morph": "23.0.0" @@ -6229,9 +6229,9 @@ } }, "node_modules/mikro-orm": { - "version": "6.3.12", - "resolved": "https://registry.npmjs.org/mikro-orm/-/mikro-orm-6.3.12.tgz", - "integrity": "sha512-CMLaxhq7EANGI0JD3EEhyafGf3fZh5ATvG1kNP/20DBarZBYSsp2GGzxhEENs0SCOVy5+dWWRL8vSuke/hIKEw==", + "version": "6.3.13", + "resolved": "https://registry.npmjs.org/mikro-orm/-/mikro-orm-6.3.13.tgz", + "integrity": "sha512-la2qeQjTMcpctz7hWs+sIe+qC3uNRe8e0Tv7aVw0ZTG3YcZe14lRWtaHM1HMc1Xdt/Fj1buxLx+yFCpiPZx5VQ==", "engines": { "node": ">= 18.12.0" } diff --git a/package.json b/package.json index 64e7918e..b9f94c13 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "author": "Sleepy Studios", "license": "MIT", "devDependencies": { - "@mikro-orm/cli": "^6.3.12", + "@mikro-orm/cli": "^6.3.13", "@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.12", - "@mikro-orm/migrations": "^6.3.12", - "@mikro-orm/mysql": "^6.3.12", - "@mikro-orm/reflection": "^6.3.12", + "@mikro-orm/core": "^6.3.13", + "@mikro-orm/migrations": "^6.3.13", + "@mikro-orm/mysql": "^6.3.13", + "@mikro-orm/reflection": "^6.3.13", "@sendgrid/mail": "^8.1.3", "@sentry/node": "^7.47.0", "@sentry/utils": "^7.47.0", From 74799cd837b02ec003b68bff0c14d784e76a6de0 Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Mon, 14 Oct 2024 21:11:07 +0100 Subject: [PATCH 3/9] service and identifier cannot be empty --- src/services/api/player-api.service.ts | 22 ++++++++++-- .../services/_api/player-api/identify.test.ts | 36 +++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/services/api/player-api.service.ts b/src/services/api/player-api.service.ts index 84eb8f84..3c7ac250 100644 --- a/src/services/api/player-api.service.ts +++ b/src/services/api/player-api.service.ts @@ -1,5 +1,5 @@ import { EntityManager } from '@mikro-orm/mysql' -import { Request, Response, Routes, Validate, HasPermission, ForwardTo, forwardRequest } from 'koa-clay' +import { Request, Response, Routes, Validate, HasPermission, ForwardTo, forwardRequest, ValidationCondition } from 'koa-clay' import APIKey, { APIKeyScope } from '../../entities/api-key' import Player from '../../entities/player' import GameSave from '../../entities/game-save' @@ -70,6 +70,15 @@ export async function createPlayerFromIdentifyRequest( } } +function validateIdentifyQueryParam(param: 'service' | 'identifier') { + return async (val?: string): Promise => [ + { + check: (val ?? '').trim().length > 0, + error: `Invalid ${param}, must be a non-empty string` + } + ] +} + @Routes([ { method: 'GET', @@ -90,7 +99,16 @@ export async function createPlayerFromIdentifyRequest( ]) export default class PlayerAPIService extends APIService { @Validate({ - query: ['service', 'identifier'] + query: { + service: { + required: true, + validation: validateIdentifyQueryParam('service') + }, + identifier: { + required: true, + validation: validateIdentifyQueryParam('identifier') + } + } }) @HasPermission(PlayerAPIPolicy, 'identify') @ForwardTo('games.players', 'post') diff --git a/tests/services/_api/player-api/identify.test.ts b/tests/services/_api/player-api/identify.test.ts index 13a7dda7..5cfa5714 100644 --- a/tests/services/_api/player-api/identify.test.ts +++ b/tests/services/_api/player-api/identify.test.ts @@ -124,4 +124,40 @@ 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 require the service to be a non-empty string', async () => { + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.READ_PLAYERS]) + const player = await new PlayerFactory([apiKey.game]).one() + await (global.em).persistAndFlush(player) + + const res = await request(global.app) + .get('/v1/players/identify') + .query({ service: '', identifier: player.aliases[0].identifier }) + .auth(token, { type: 'bearer' }) + .expect(400) + + expect(res.body).toStrictEqual({ + errors: { + service: ['Invalid service, must be a non-empty string'] + } + }) + }) + + it('should require the identifier to be a non-empty string', async () => { + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.READ_PLAYERS]) + const player = await new PlayerFactory([apiKey.game]).one() + await (global.em).persistAndFlush(player) + + const res = await request(global.app) + .get('/v1/players/identify') + .query({ service: player.aliases[0].service, identifier: '' }) + .auth(token, { type: 'bearer' }) + .expect(400) + + expect(res.body).toStrictEqual({ + errors: { + identifier: ['Invalid identifier, must be a non-empty string'] + } + }) + }) }) From ee592f7cf29393c2c0ed97d8d0af2b25cfab4f73 Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Mon, 14 Oct 2024 21:28:01 +0100 Subject: [PATCH 4/9] additional tests for missing query params --- .../services/_api/player-api/identify.test.ts | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/services/_api/player-api/identify.test.ts b/tests/services/_api/player-api/identify.test.ts index 5cfa5714..f72aeda5 100644 --- a/tests/services/_api/player-api/identify.test.ts +++ b/tests/services/_api/player-api/identify.test.ts @@ -125,6 +125,24 @@ 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 require the service to be set', async () => { + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.READ_PLAYERS]) + const player = await new PlayerFactory([apiKey.game]).one() + await (global.em).persistAndFlush(player) + + const res = await request(global.app) + .get('/v1/players/identify') + .query({ identifier: player.aliases[0].identifier }) + .auth(token, { type: 'bearer' }) + .expect(400) + + expect(res.body).toStrictEqual({ + errors: { + service: ['service is missing from the request query'] + } + }) + }) + it('should require the service to be a non-empty string', async () => { const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.READ_PLAYERS]) const player = await new PlayerFactory([apiKey.game]).one() @@ -143,6 +161,24 @@ describe('Player API service - identify', () => { }) }) + it('should require the identifier to be set', async () => { + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.READ_PLAYERS]) + const player = await new PlayerFactory([apiKey.game]).one() + await (global.em).persistAndFlush(player) + + const res = await request(global.app) + .get('/v1/players/identify') + .query({ service: player.aliases[0].service }) + .auth(token, { type: 'bearer' }) + .expect(400) + + expect(res.body).toStrictEqual({ + errors: { + identifier: ['identifier is missing from the request query'] + } + }) + }) + it('should require the identifier to be a non-empty string', async () => { const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.READ_PLAYERS]) const player = await new PlayerFactory([apiKey.game]).one() From 5adf09a2f71f1c5a5a2b7f34f147634a61d568d9 Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Fri, 18 Oct 2024 17:13:26 +0100 Subject: [PATCH 5/9] add api for fetching a player group --- src/config/api-routes.ts | 2 + src/docs/player-group-api.docs.ts | 81 +++++++++++++++++++ src/entities/api-key.ts | 1 + src/entities/player-group.ts | 11 +++ src/migrations/.snapshot-gs_dev.json | 11 +++ ...02844AddPlayerGroupMembersVisibleColumn.ts | 13 +++ src/migrations/index.ts | 5 ++ src/policies/api/player-group-api.policy.ts | 21 +++++ src/services/api/player-group-api.service.ts | 28 +++++++ src/services/player-group.service.ts | 21 ++--- .../_api/player-group-api/index.test.ts | 74 +++++++++++++++++ 11 files changed, 254 insertions(+), 14 deletions(-) create mode 100644 src/docs/player-group-api.docs.ts create mode 100644 src/migrations/20241014202844AddPlayerGroupMembersVisibleColumn.ts create mode 100644 src/policies/api/player-group-api.policy.ts create mode 100644 src/services/api/player-group-api.service.ts create mode 100644 tests/services/_api/player-group-api/index.test.ts diff --git a/src/config/api-routes.ts b/src/config/api-routes.ts index ba45a449..bc19e148 100644 --- a/src/config/api-routes.ts +++ b/src/config/api-routes.ts @@ -15,6 +15,7 @@ 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' +import PlayerGroupAPIService from '../services/api/player-group-api.service' export default (app: Koa) => { app.use(apiKeyMiddleware) @@ -31,6 +32,7 @@ export default (app: Koa) => { app.use(playerAuthMiddleware) app.use(continunityMiddleware) + app.use(service('/v1/player-groups', new PlayerGroupAPIService())) app.use(service('/v1/health-check', new HealthCheckAPIService())) app.use(service('/v1/game-feedback', new GameFeedbackAPIService())) app.use(service('/v1/game-config', new GameConfigAPIService())) diff --git a/src/docs/player-group-api.docs.ts b/src/docs/player-group-api.docs.ts new file mode 100644 index 00000000..56db10fb --- /dev/null +++ b/src/docs/player-group-api.docs.ts @@ -0,0 +1,81 @@ +import PlayerGroupAPIService from '../services/api/player-group-api.service' +import APIDocs from './api-docs' + +const PlayerGroupAPIDocs: APIDocs = { + get: { + description: 'Get a group and its members', + samples: [ + { + title: 'Sample response (members visible)', + sample: { + group: { + id: '74b6a013-6c3d-4de6-8f61-444b4cf6e909', + name: 'Online players', + description: 'Players that are currently online', + rules: [ + { + name: 'EQUALS', + negate: false, + field: 'props.online', + castType: 'CHAR', + operands: [ + 'true' + ] + } + ], + ruleMode: '$and', + updatedAt: '2024-10-01T23:09:18.000Z', + count: 1, + members: [ + { + id: '714b38f5-1dee-4243-a54c-50fb1cfe2e4e', + props: [ + { + key: 'online', + value: 'true' + } + ], + aliases: [], + devBuild: false, + createdAt: '2024-09-29T14:14:34.000Z', + lastSeenAt: '2024-10-03T08:03:16.000Z', + groups: [ + { + id: '74b6a013-6c3d-4de6-8f61-444b4cf6e909', + name: 'Online players' + } + ] + } + ] + } + } + }, + { + title: 'Sample response (members not visible)', + sample: { + group: { + id: '74b6a013-6c3d-4de6-8f61-444b4cf6e909', + name: 'Online players', + description: 'Players that are currently online', + rules: [ + { + name: 'EQUALS', + negate: false, + field: 'props.online', + castType: 'CHAR', + operands: [ + 'true' + ] + } + ], + ruleMode: '$and', + updatedAt: '2024-10-01T23:09:18.000Z', + count: 1 + } + } + } + ] + } +} + +export default PlayerGroupAPIDocs diff --git a/src/entities/api-key.ts b/src/entities/api-key.ts index 70cdd0ed..9856156c 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 { + READ_PLAYER_GROUPS = 'read:playerGroups', WRITE_CONTINUITY_REQUESTS = 'write:continuityRequests', READ_GAME_FEEDBACK = 'read:gameFeedback', WRITE_GAME_FEEDBACK = 'write:gameFeedback', diff --git a/src/entities/player-group.ts b/src/entities/player-group.ts index 63375cdf..dec7f0ef 100644 --- a/src/entities/player-group.ts +++ b/src/entities/player-group.ts @@ -48,6 +48,10 @@ export default class PlayerGroup { @Property() description: string + @Required() + @Property({ default: false }) + membersVisible: boolean + @Required({ validation: rulesValidation }) @@ -106,4 +110,11 @@ export default class PlayerGroup { updatedAt: this.updatedAt } } + + async toJSONWithCount() { + return { + ...this.toJSON(), + count: await this.members.loadCount() + } + } } diff --git a/src/migrations/.snapshot-gs_dev.json b/src/migrations/.snapshot-gs_dev.json index 76410afd..cfaa7217 100644 --- a/src/migrations/.snapshot-gs_dev.json +++ b/src/migrations/.snapshot-gs_dev.json @@ -791,6 +791,17 @@ "length": 255, "mappedType": "string" }, + "members_visible": { + "name": "public", + "type": "tinyint(1)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 1, + "default": "false", + "mappedType": "boolean" + }, "rules": { "name": "rules", "type": "json", diff --git a/src/migrations/20241014202844AddPlayerGroupMembersVisibleColumn.ts b/src/migrations/20241014202844AddPlayerGroupMembersVisibleColumn.ts new file mode 100644 index 00000000..f1c6bf80 --- /dev/null +++ b/src/migrations/20241014202844AddPlayerGroupMembersVisibleColumn.ts @@ -0,0 +1,13 @@ +import { Migration } from '@mikro-orm/migrations' + +export class AddPlayerGroupMembersVisibleColumn extends Migration { + + override async up(): Promise { + this.addSql('alter table `player_group` add `members_visible` tinyint(1) not null default false;') + } + + override async down(): Promise { + this.addSql('alter table `player_group` drop column `members_visible`;') + } + +} diff --git a/src/migrations/index.ts b/src/migrations/index.ts index b93724b6..92e0dd7c 100644 --- a/src/migrations/index.ts +++ b/src/migrations/index.ts @@ -30,6 +30,7 @@ import { UpdatePlayerAliasServiceColumn } from './20240916213402UpdatePlayerAlia import { AddPlayerAliasAnonymisedColumn } from './20240920121232AddPlayerAliasAnonymisedColumn' import { AddLeaderboardEntryPropsColumn } from './20240922222426AddLeaderboardEntryPropsColumn' import { CreateUserPinnedGroupsTable } from './20241001194252CreateUserPinnedGroupsTable' +import { AddPlayerGroupMembersVisibleColumn } from './20241014202844AddPlayerGroupMembersVisibleColumn' export default [ { @@ -159,5 +160,9 @@ export default [ { name: 'CreateUserPinnedGroupsTable', class: CreateUserPinnedGroupsTable + }, + { + name: 'AddPlayerGroupMembersVisibleColumn', + class: AddPlayerGroupMembersVisibleColumn } ] diff --git a/src/policies/api/player-group-api.policy.ts b/src/policies/api/player-group-api.policy.ts new file mode 100644 index 00000000..45efd7fd --- /dev/null +++ b/src/policies/api/player-group-api.policy.ts @@ -0,0 +1,21 @@ +import Policy from '../policy' +import { PolicyDenial, PolicyResponse, Request } from 'koa-clay' +import { APIKeyScope } from '../../entities/api-key' +import PlayerGroup from '../../entities/player-group' + +export default class PlayerGroupAPIPolicy extends Policy { + async get(req: Request): Promise { + const { id } = req.params + + const key = await this.getAPIKey() + const group = await this.em.getRepository(PlayerGroup).findOne({ + id, + game: key.game + }) + + this.ctx.state.group = group + if (!group) return new PolicyDenial({ message: 'Group not found' }, 404) + + return await this.hasScope(APIKeyScope.READ_PLAYER_GROUPS) + } +} diff --git a/src/services/api/player-group-api.service.ts b/src/services/api/player-group-api.service.ts new file mode 100644 index 00000000..13437787 --- /dev/null +++ b/src/services/api/player-group-api.service.ts @@ -0,0 +1,28 @@ +import { HasPermission, Request, Response, Docs } from 'koa-clay' +import APIService from './api-service' +import PlayerGroupAPIPolicy from '../../policies/api/player-group-api.policy' +import PlayerGroup from '../../entities/player-group' +import Player from '../../entities/player' +import PlayerGroupAPIDocs from '../../docs/player-group-api.docs' + +type PlayerGroupWithCountAndMembers = Pick & { count: number, members?: Player[] } + +export default class PlayerGroupAPIService extends APIService { + @HasPermission(PlayerGroupAPIPolicy, 'get') + @Docs(PlayerGroupAPIDocs.get) + async get(req: Request): Promise { + const group: PlayerGroup = req.ctx.state.group + + const groupWithCountAndMembers: PlayerGroupWithCountAndMembers = await group.toJSONWithCount() + if (group.membersVisible) { + groupWithCountAndMembers.members = await group.members.loadItems() + } + + return { + status: 200, + body: { + group: groupWithCountAndMembers + } + } + } +} diff --git a/src/services/player-group.service.ts b/src/services/player-group.service.ts index 4df9d37f..ac9c369c 100644 --- a/src/services/player-group.service.ts +++ b/src/services/player-group.service.ts @@ -9,8 +9,6 @@ import PlayerGroupPolicy from '../policies/player-group.policy' import getUserFromToken from '../lib/auth/getUserFromToken' import UserPinnedGroup from '../entities/user-pinned-group' -type PlayerGroupWithCount = Pick & { count: number } - @Routes([ { method: 'GET' @@ -46,13 +44,6 @@ type PlayerGroupWithCount = Pick { - return { - ...group.toJSON(), - count: await group.members.loadCount() - } - } - @HasPermission(PlayerGroupPolicy, 'index') async index(req: Request): Promise { const em: EntityManager = req.ctx.em @@ -61,7 +52,7 @@ export default class PlayerGroupService extends Service { return { status: 200, body: { - groups: await Promise.all(groups.map(this.groupWithCount)) + groups: await Promise.all(groups.map((group) => group.toJSONWithCount())) } } } @@ -79,7 +70,7 @@ export default class PlayerGroupService extends Service { @Validate({ body: [PlayerGroup] }) @HasPermission(PlayerGroupPolicy, 'post') async post(req: Request): Promise { - const { name, description, ruleMode, rules } = req.body + const { name, description, ruleMode, rules, membersVisible } = req.body const em: EntityManager = req.ctx.em const group = new PlayerGroup(req.ctx.state.game) @@ -87,6 +78,7 @@ export default class PlayerGroupService extends Service { group.description = description group.ruleMode = ruleMode group.rules = this.buildRulesFromData(rules) + group.membersVisible = membersVisible await group.checkMembership(em) createGameActivity(em, { @@ -103,7 +95,7 @@ export default class PlayerGroupService extends Service { return { status: 200, body: { - group: await this.groupWithCount(group) + group: await group.toJSONWithCount() } } } @@ -111,7 +103,7 @@ export default class PlayerGroupService extends Service { @Validate({ body: [PlayerGroup] }) @HasPermission(PlayerGroupPolicy, 'put') async put(req: Request): Promise { - const { name, description, ruleMode, rules } = req.body + const { name, description, ruleMode, rules, membersVisible } = req.body const em: EntityManager = req.ctx.em const group: PlayerGroup = req.ctx.state.group @@ -119,6 +111,7 @@ export default class PlayerGroupService extends Service { group.description = description group.ruleMode = ruleMode group.rules = this.buildRulesFromData(rules) + group.membersVisible = membersVisible await group.checkMembership(em) createGameActivity(em, { @@ -260,7 +253,7 @@ export default class PlayerGroupService extends Service { orderBy: { createdAt: 'desc' } }) - const groups = await Promise.all(pinnedGroups.map(({ group }) => this.groupWithCount(group))) + const groups = await Promise.all(pinnedGroups.map(({ group }) => group.toJSONWithCount())) return { status: 200, diff --git a/tests/services/_api/player-group-api/index.test.ts b/tests/services/_api/player-group-api/index.test.ts new file mode 100644 index 00000000..539dadd4 --- /dev/null +++ b/tests/services/_api/player-group-api/index.test.ts @@ -0,0 +1,74 @@ +import { EntityManager } from '@mikro-orm/mysql' +import request from 'supertest' +import { APIKeyScope } from '../../../../src/entities/api-key' +import createAPIKeyAndToken from '../../../utils/createAPIKeyAndToken' +import PlayerFactory from '../../../fixtures/PlayerFactory' +import PlayerGroupRule, { PlayerGroupRuleCastType, PlayerGroupRuleName } from '../../../../src/entities/player-group-rule' +import PlayerGroupFactory from '../../../fixtures/PlayerGroupFactory' + +describe('Player group API service - get', () => { + it('should return a group if the scope is valid', async () => { + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.READ_PLAYER_GROUPS]) + await (global.em).populate(apiKey, ['game']) + + const player = await new PlayerFactory([apiKey.game]).state(() => ({ lastSeenAt: new Date(2024, 1, 2) })).one() + const dateRule = new PlayerGroupRule(PlayerGroupRuleName.GTE, 'lastSeenAt') + dateRule.castType = PlayerGroupRuleCastType.DATETIME + dateRule.operands = ['2024-01-01'] + + const group = await new PlayerGroupFactory().construct(apiKey.game).state(() => ({ rules: [dateRule], membersVisible: true })).one() + await (global.em).persistAndFlush([player, group]) + + const res = await request(global.app) + .get(`/v1/player-groups/${group.id}`) + .auth(token, { type: 'bearer' }) + .expect(200) + + expect(res.body.group.id).toBe(group.id) + expect(res.body.group.count).toBe(1) + expect(res.body.group.members).toHaveLength(1) + }) + + it('should not return a group if the scope is not valid', async () => { + const [apiKey, token] = await createAPIKeyAndToken([]) + + const group = await new PlayerGroupFactory().construct(apiKey.game).state(() => ({ rules: [] })).one() + await (global.em).persistAndFlush(group) + + await request(global.app) + .get(`/v1/player-groups/${group.id}`) + .auth(token, { type: 'bearer' }) + .expect(403) + }) + + it('should not return a non-existent group', async () => { + const [, token] = await createAPIKeyAndToken([]) + + await request(global.app) + .get('/v1/player-groups/abcdef') + .auth(token, { type: 'bearer' }) + .expect(404) + }) + + it('should not return group members if membersVisible is set to false', async () => { + const [apiKey, token] = await createAPIKeyAndToken([APIKeyScope.READ_PLAYER_GROUPS]) + await (global.em).populate(apiKey, ['game']) + + const player = await new PlayerFactory([apiKey.game]).state(() => ({ lastSeenAt: new Date(2024, 1, 2) })).one() + const dateRule = new PlayerGroupRule(PlayerGroupRuleName.GTE, 'lastSeenAt') + dateRule.castType = PlayerGroupRuleCastType.DATETIME + dateRule.operands = ['2024-01-01'] + + const group = await new PlayerGroupFactory().construct(apiKey.game).state(() => ({ rules: [dateRule], membersVisible: false })).one() + await (global.em).persistAndFlush([player, group]) + + const res = await request(global.app) + .get(`/v1/player-groups/${group.id}`) + .auth(token, { type: 'bearer' }) + .expect(200) + + expect(res.body.group.id).toBe(group.id) + expect(res.body.group.count).toBe(1) + expect(res.body.group.members).toBeUndefined() + }) +}) From 18a8a8c024d5bb0a9311feff41b22c53f49f6f03 Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Fri, 18 Oct 2024 19:53:54 +0100 Subject: [PATCH 6/9] update docs, include membersVisible in json --- src/docs/player-group-api.docs.ts | 7 +++++++ src/entities/player-group.ts | 1 + src/services/player-group.service.ts | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/docs/player-group-api.docs.ts b/src/docs/player-group-api.docs.ts index 56db10fb..d8c04728 100644 --- a/src/docs/player-group-api.docs.ts +++ b/src/docs/player-group-api.docs.ts @@ -4,6 +4,11 @@ import APIDocs from './api-docs' const PlayerGroupAPIDocs: APIDocs = { get: { description: 'Get a group and its members', + params: { + route: { + id: 'The ID of the group' + } + }, samples: [ { title: 'Sample response (members visible)', @@ -24,6 +29,7 @@ const PlayerGroupAPIDocs: APIDocs = { } ], ruleMode: '$and', + membersVisible: true, updatedAt: '2024-10-01T23:09:18.000Z', count: 1, members: [ @@ -69,6 +75,7 @@ const PlayerGroupAPIDocs: APIDocs = { } ], ruleMode: '$and', + membersVisible: false, updatedAt: '2024-10-01T23:09:18.000Z', count: 1 } diff --git a/src/entities/player-group.ts b/src/entities/player-group.ts index dec7f0ef..4ba1b859 100644 --- a/src/entities/player-group.ts +++ b/src/entities/player-group.ts @@ -107,6 +107,7 @@ export default class PlayerGroup { description: this.description, rules: this.rules, ruleMode: this.ruleMode, + membersVisible: this.membersVisible, updatedAt: this.updatedAt } } diff --git a/src/services/player-group.service.ts b/src/services/player-group.service.ts index ac9c369c..68c42a1a 100644 --- a/src/services/player-group.service.ts +++ b/src/services/player-group.service.ts @@ -128,7 +128,7 @@ export default class PlayerGroupService extends Service { return { status: 200, body: { - group + group: await group.toJSONWithCount() } } } From a754f533e8c301d51185f42d7d7e761f48bb9a7f Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Sat, 19 Oct 2024 00:20:34 +0100 Subject: [PATCH 7/9] fix tests --- tests/services/player-group/post.test.ts | 30 ++++++++++++++++-------- tests/services/player-group/put.test.ts | 12 ++++++---- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/tests/services/player-group/post.test.ts b/tests/services/player-group/post.test.ts index 241adff6..b3fdd757 100644 --- a/tests/services/player-group/post.test.ts +++ b/tests/services/player-group/post.test.ts @@ -33,7 +33,8 @@ describe('Player group service - post', () => { name: 'Winners', description: 'People who have completed the game', ruleMode: '$and', - rules + rules, + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(statusCode) @@ -85,7 +86,8 @@ describe('Player group service - post', () => { name: 'Winners', description: 'People who have completed the game', ruleMode: '$and', - rules + rules, + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(200) @@ -103,7 +105,8 @@ describe('Player group service - post', () => { name: 'Winners', description: 'People who have completed the game', ruleMode: '$not', - rules: [] + rules: [], + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(400) @@ -125,7 +128,8 @@ describe('Player group service - post', () => { name: 'Winners', description: 'People who have completed the game', ruleMode: '$and', - rules: {} + rules: {}, + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(400) @@ -155,7 +159,8 @@ describe('Player group service - post', () => { negate: false, castType: PlayerGroupRuleCastType.CHAR } - ] + ], + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(400) @@ -185,7 +190,8 @@ describe('Player group service - post', () => { negate: false, castType: 'VARCHAR' } - ] + ], + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(400) @@ -215,7 +221,8 @@ describe('Player group service - post', () => { negate: 'no', castType: PlayerGroupRuleCastType.CHAR } - ] + ], + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(400) @@ -245,7 +252,8 @@ describe('Player group service - post', () => { negate: false, castType: PlayerGroupRuleCastType.CHAR } - ] + ], + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(400) @@ -267,7 +275,8 @@ describe('Player group service - post', () => { name: 'Winners', description: 'People who have completed the game', ruleMode: '$and', - rules: [] + rules: [], + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(403) @@ -284,7 +293,8 @@ describe('Player group service - post', () => { name: 'Winners', description: 'People who have completed the game', ruleMode: '$and', - rules: [] + rules: [], + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(404) diff --git a/tests/services/player-group/put.test.ts b/tests/services/player-group/put.test.ts index 3de4eb62..66ea622c 100644 --- a/tests/services/player-group/put.test.ts +++ b/tests/services/player-group/put.test.ts @@ -37,7 +37,8 @@ describe('Player group service - put', () => { name: 'Winners', description: 'People who have completed the game', ruleMode: '$and', - rules + rules, + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(statusCode) @@ -91,7 +92,8 @@ describe('Player group service - put', () => { name: 'Winners', description: 'People who have completed the game', ruleMode: '$and', - rules + rules, + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(200) @@ -113,7 +115,8 @@ describe('Player group service - put', () => { name: 'Winners', description: 'People who have completed the game', ruleMode: '$and', - rules: [] + rules: [], + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(403) @@ -131,7 +134,8 @@ describe('Player group service - put', () => { name: 'Winners', description: 'People who have completed the game', ruleMode: '$and', - rules: [] + rules: [], + membersVisible: false }) .auth(token, { type: 'bearer' }) .expect(404) From bb2a7c4e6c410c800f48ded70b0e450d01cc3769 Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Sat, 19 Oct 2024 00:34:55 +0100 Subject: [PATCH 8/9] val can never be empty because required runs first --- src/services/api/player-api.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/api/player-api.service.ts b/src/services/api/player-api.service.ts index 3c7ac250..c84fd55c 100644 --- a/src/services/api/player-api.service.ts +++ b/src/services/api/player-api.service.ts @@ -73,7 +73,7 @@ export async function createPlayerFromIdentifyRequest( function validateIdentifyQueryParam(param: 'service' | 'identifier') { return async (val?: string): Promise => [ { - check: (val ?? '').trim().length > 0, + check: val.trim().length > 0, error: `Invalid ${param}, must be a non-empty string` } ] From 97de94aeee2811a22116e85c651026fd69504157 Mon Sep 17 00:00:00 2001 From: tudor <7089284+tudddorrr@users.noreply.github.com> Date: Sun, 20 Oct 2024 09:53:52 +0100 Subject: [PATCH 9/9] 0.46.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 3e765fd6..60e66517 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "game-services", - "version": "0.45.0", + "version": "0.46.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "game-services", - "version": "0.45.0", + "version": "0.46.0", "license": "MIT", "dependencies": { "@clickhouse/client": "^1.4.1", diff --git a/package.json b/package.json index b9f94c13..b7c12d36 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "game-services", - "version": "0.45.0", + "version": "0.46.0", "description": "", "main": "src/index.ts", "scripts": {