Further login process
* APIUtils addition: query validation * Coach and Server accounts are now properly created if they do not exist * Profiles now cannot be IDs 1 or 2 (reservedIds) * Fixed profile username exists bug * Added relationship manager * Started relationship management * DeviceClass and VRMovementMode enum defaults for reserved profiles * Presence update simplification * Progression fixes * Relationship query and object fixes * Base configuration is now rate limited * Progression route no longer requires authentication, instead is rate limited * Base relationships with reserved profiles (Coach and Server) * DeviceClass required for login * Get presence route * Socket route no longer logs * Socket target base finished
This commit is contained in:
@@ -28,6 +28,12 @@ route.router.post("/create",
|
||||
|
||||
async (_rq, rs) => {
|
||||
const newAcc = await Profile.init();
|
||||
if (newAcc == null) {
|
||||
rs.json({
|
||||
success: false
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
rs.locals.user.addAssociatedProfile(newAcc.getId());
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@ import { GameConfigs } from "../../data/config.ts";
|
||||
|
||||
export const route = APIUtils.createRouter("/config");
|
||||
|
||||
route.router.get("/v2", (_rq, rs) => {
|
||||
const rateLimit = new APIUtils.RateLimiter(60, 2);
|
||||
|
||||
route.router.get("/v2", rateLimit.middle(), (_rq, rs) => {
|
||||
const config = GameConfigs.getConfig();
|
||||
if (config == null) rs.sendStatus(500);
|
||||
else rs.json(config);
|
||||
@@ -11,6 +13,7 @@ route.router.get("/v2", (_rq, rs) => {
|
||||
|
||||
route.router.get('/v1/amplitude',
|
||||
APIUtils.setCacheAllowed,
|
||||
rateLimit.middle(),
|
||||
(_rq, rs) => {
|
||||
rs.json({AmplitudeKey: ""});
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ route.router.get('/v1/:id',
|
||||
APIUtils.Authentication,
|
||||
APIUtils.AuthenticationType(AuthType.Game),
|
||||
|
||||
(rq: express.Request<{ id: string }>, rs) => {
|
||||
async (rq: express.Request<{ id: string }>, rs) => {
|
||||
const unparsedPlayerId = rq.params.id;
|
||||
const parsedPlayerId = parseInt(unparsedPlayerId);
|
||||
if (isNaN(parsedPlayerId)) {
|
||||
@@ -18,7 +18,7 @@ route.router.get('/v1/:id',
|
||||
return;
|
||||
}
|
||||
|
||||
rs.json(UnifiedProfile.get(parsedPlayerId).Reputation.getReputation());
|
||||
rs.json(await UnifiedProfile.get(parsedPlayerId).Reputation.getReputation());
|
||||
}
|
||||
|
||||
);
|
||||
@@ -5,11 +5,13 @@ import UnifiedProfile from "../../data/profiles.ts";
|
||||
|
||||
const log = new Logging("ProgressionRoute");
|
||||
|
||||
const rateLimit = new APIUtils.RateLimiter(60, 2);
|
||||
|
||||
export const route = APIUtils.createRouter("/players");
|
||||
|
||||
route.router.get('/v1/progression/:id',
|
||||
|
||||
APIUtils.Authentication,
|
||||
rateLimit.middle(),
|
||||
|
||||
async (rq: express.Request<{ id: string }>, rs) => {
|
||||
const unparsedPlayerId = rq.params.id;
|
||||
|
||||
@@ -9,7 +9,7 @@ route.router.get('/v2/get',
|
||||
APIUtils.AuthenticationType(AuthType.Game),
|
||||
|
||||
(_rq, rs) => {
|
||||
rs.json([]); // temporary
|
||||
rs.json(rs.locals.profile.Relationships.getRelationships());
|
||||
}
|
||||
|
||||
);
|
||||
@@ -98,6 +98,7 @@ route.router.post("/token",
|
||||
rq.body.platform === "0",
|
||||
rq.body.ver === '20191120',
|
||||
rq.body.device_class.length === 1,
|
||||
!isNaN(Number(rq.body.device_class)),
|
||||
!(rq.body.device_id.length > 96),
|
||||
!(rq.body.client_secret.length > 96),
|
||||
!(rq.body.platform_id.length > 32),
|
||||
@@ -110,9 +111,8 @@ route.router.post("/token",
|
||||
return;
|
||||
}
|
||||
|
||||
const accounts = await rs.locals.user.getAssociatedProfiles();
|
||||
let targetAccount: number;
|
||||
|
||||
|
||||
if (rq.body.grant_type == 'cached_login') targetAccount = parseInt(rq.body.account_id);
|
||||
else {
|
||||
const refreshToken = rq.body.refresh_token;
|
||||
@@ -128,15 +128,17 @@ route.router.post("/token",
|
||||
requestFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
targetAccount = parseInt(decodedToken.sub ? decodedToken.sub : "NaN");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (isNaN(targetAccount)) {
|
||||
requestFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
const accounts = await rs.locals.user.getAssociatedProfiles();
|
||||
if (!accounts.has(targetAccount)) {
|
||||
requestFailed("access_denied");
|
||||
return;
|
||||
@@ -160,6 +162,6 @@ route.router.post("/token",
|
||||
refresh_token: token,
|
||||
});
|
||||
|
||||
await profile.setKnownDeviceClass(rq.body.device_class);
|
||||
await profile.setKnownDeviceClass(Number(rq.body.device_class));
|
||||
},
|
||||
);
|
||||
|
||||
@@ -2,9 +2,10 @@ import { z } from "zod";
|
||||
import { APIUtils, NoBody } from "../../apiutils.ts";
|
||||
import express from "express";
|
||||
import Matchmaking from "../../data/live/base.ts";
|
||||
import Presence from "../../data/live/presence.ts";
|
||||
import Presence, { PresenceExport } from "../../data/live/presence.ts";
|
||||
import { AuthType } from "../../data/users.ts";
|
||||
import Logging from "@proxnet/undead-logging";
|
||||
import UnifiedProfile from "../../data/profiles.ts";
|
||||
|
||||
const log = new Logging("MatchPlayerRoute");
|
||||
|
||||
@@ -18,6 +19,31 @@ const LoginSchema = z.object({
|
||||
LoginLock: z.string().uuid("LoginLock must be a UUIDv4")
|
||||
});
|
||||
|
||||
route.router.get('/',
|
||||
|
||||
APIUtils.Authentication,
|
||||
APIUtils.AuthenticationType(AuthType.Game),
|
||||
APIUtils.validateQuery(z.object({ id: z.union([z.string(), z.array(z.string())]) })),
|
||||
|
||||
async (rq: express.Request<NoBody, PresenceExport[], NoBody, { id: string[] | string }>, rs) => {
|
||||
let ids: number[] = [];
|
||||
if (typeof rq.query.id == 'object') ids = rq.query.id.map(val => parseInt(val));
|
||||
else ids.push(parseInt(rq.query.id));
|
||||
ids = ids.filter(val => !isNaN(val));
|
||||
|
||||
const presExport: PresenceExport[] = [];
|
||||
for (const id of ids) {
|
||||
const pres = await Presence.get(UnifiedProfile.get(id));
|
||||
await pres.update();
|
||||
presExport.push(await pres.export());
|
||||
}
|
||||
|
||||
rs.json(presExport);
|
||||
log.d(JSON.stringify(presExport));
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
route.router.post('/login',
|
||||
|
||||
APIUtils.Authentication,
|
||||
@@ -40,8 +66,9 @@ route.router.post('/logout',
|
||||
express.urlencoded({extended: true}),
|
||||
APIUtils.validateRequestBody(LoginSchema),
|
||||
|
||||
(rq, rs) => {
|
||||
(_rq, rs) => {
|
||||
Matchmaking.deleteLoginLock(rs.locals.profile);
|
||||
rs.sendStatus(200);
|
||||
}
|
||||
|
||||
)
|
||||
@@ -56,6 +83,7 @@ route.router.post('/heartbeat',
|
||||
|
||||
async (_rq, rs) => {
|
||||
const pres = await Presence.get(rs.locals.profile);
|
||||
await pres.update();
|
||||
log.d(`pres heartbeat for ${rs.locals.profile.getId()}: ${JSON.stringify(await pres.export())}`);
|
||||
rs.json(await pres.export());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user