Many changes. Commit before I break down.

- Authentication middleware uses Zod
- PhotonRegionId in config
- DB key changes and additions
- WebSocket for SignalR mock
- Presence additions
  * Needs modification for playerIds (do not store `Profile` in a set, this will cause sync issues)
- Profile settings
- Profile Device Class
- Zod properly checks for issuer in token
- Room scene type bug
- Setting key import started
- Instancing changes
- PlayerReporting API route
- Deduplicated auth/connect/token
- match/player/login begin
- WebSocket hands off connection to SignalR handler
This commit is contained in:
2025-03-27 00:44:58 -04:00
parent 3538321487
commit c920dbe88a
23 changed files with 792 additions and 194 deletions

View File

@@ -1,6 +1,7 @@
import { route as VersionCheckRoute } from "./api/versioncheck.ts";
import { route as ConfigRoute } from "./api/config.ts";
import { route as GameConfig } from "./api/gameconfigs.ts";
import { route as PlayerReportingRoute } from "./api/PlayerReporting.ts";
import { APIUtils } from "../apiutils.ts";
export const route = APIUtils.createRouter("/api");
@@ -8,3 +9,4 @@ export const route = APIUtils.createRouter("/api");
route.router.use(VersionCheckRoute.path, VersionCheckRoute.router);
route.router.use(ConfigRoute.path, ConfigRoute.router);
route.router.use(GameConfig.path, GameConfig.router);
route.router.use(PlayerReportingRoute.path, PlayerReportingRoute.router);

View File

@@ -26,4 +26,20 @@ route.router.post('/v1/hile',
log.w(`Client sent hile report: '${rq.body.Message}'`);
},
);
route.router.get('/v1/moderationBlockDetails',
APIUtils.Authentication,
(_rq, rs) => {
// todo: moderation
rs.json({
ReportCategory: 0,
Duration: 0,
GameSessionId: 0,
Message: ""
});
}
);

View File

@@ -76,7 +76,6 @@ route.router.post("/token",
APIUtils.Authentication,
express.urlencoded({ extended: true }),
APIUtils.logBody,
APIUtils.validateRequestBody<AuthBodyBase>(TokenRequestBodySchema),
async (
@@ -93,9 +92,10 @@ route.router.post("/token",
}
const conditionsMet = ![
rq.body.client_id == "recroom",
rq.body.platform == "0",
rq.body.ver == '20191120',
rq.body.client_id === "recroom",
rq.body.platform === "0",
rq.body.ver === '20191120',
rq.body.device_class.length === 1,
!(rq.body.device_id.length > 96),
!(rq.body.client_secret.length > 96),
!(rq.body.platform_id.length > 32),
@@ -107,34 +107,12 @@ route.router.post("/token",
requestFailed();
return;
}
if (rq.body.grant_type == 'cached_login') {
const accounts = await rs.locals.user.getAssociatedProfiles();
const targetAccount = parseInt(rq.body.account_id);
if (isNaN(targetAccount)) {
requestFailed();
return;
}
if (!accounts.has(targetAccount)) {
requestFailed("access_denied");
return;
}
const accounts = await rs.locals.user.getAssociatedProfiles();
let targetAccount: number;
rs.locals.user.addAssociatedDeviceId(rq.body.device_id);
rs.locals.user.addAssociatedPlatformId(rq.body.platform_id);
const profile = new Profile(targetAccount);
if (!(await Profile.exists(profile.getId()))) {
requestFailed();
return;
}
const token = await profile.getToken();
rs.json({
access_token: token,
refresh_token: token,
});
} else {
if (rq.body.grant_type == 'cached_login') targetAccount = parseInt(rq.body.account_id);
else {
const refreshToken = rq.body.refresh_token;
if (typeof refreshToken == 'undefined') {
requestFailed();
@@ -149,32 +127,34 @@ route.router.post("/token",
return;
}
const accounts = await rs.locals.user.getAssociatedProfiles();
const targetAccount = parseInt(decodedToken.sub ? decodedToken.sub : "NaN");
targetAccount = parseInt(decodedToken.sub ? decodedToken.sub : "NaN");
if (isNaN(targetAccount)) {
requestFailed();
return;
}
if (!accounts.has(targetAccount)) {
requestFailed("access_denied");
return;
}
rs.locals.user.addAssociatedDeviceId(rq.body.device_id);
rs.locals.user.addAssociatedPlatformId(rq.body.platform_id);
const profile = new Profile(targetAccount);
if (!(await Profile.exists(profile.getId()))) {
requestFailed();
return;
}
const token = await profile.getToken();
rs.json({
access_token: token,
refresh_token: token,
});
}
if (isNaN(targetAccount)) {
requestFailed();
return;
}
if (!accounts.has(targetAccount)) {
requestFailed("access_denied");
return;
}
rs.locals.user.addAssociatedDeviceId(rq.body.device_id);
rs.locals.user.addAssociatedPlatformId(rq.body.platform_id);
const profile = new Profile(targetAccount);
if (!(await Profile.exists(profile.getId()))) {
requestFailed();
return;
}
const token = await profile.getToken();
rs.json({
access_token: token,
refresh_token: token,
});
await profile.setKnownDeviceClass(rq.body.device_class);
},
);

View File

@@ -1,6 +1,8 @@
import { z } from "zod";
import { APIUtils } from "../../apiutils.ts";
import { APIUtils, NoBody } from "../../apiutils.ts";
import express from "express";
import Matchmaking from "../../data/live/base.ts";
import Presence from "../../data/live/presence.ts";
export const route = APIUtils.createRouter('/player');
@@ -18,13 +20,10 @@ route.router.post('/login',
express.urlencoded({extended: true}),
APIUtils.validateRequestBody(LoginSchema),
(_rq, rs) => {
// temporary
(rq: express.Request<NoBody, NoBody, BaseLoginLock>, rs: express.Response) => {
Matchmaking.createLoginLock(rs.locals.profile, rq.body.LoginLock);
Presence.create(rs.locals.profile);
rs.sendStatus(200);
// check for existing login
// set login lock
// init presence
// use device_class from token request
},
)