Files
partey_workadventure/pusher/src/Controller/MapController.ts
T
2021-10-21 16:23:42 +02:00

163 lines
6.4 KiB
TypeScript

import { HttpRequest, HttpResponse, TemplatedApp } from "uWebSockets.js";
import { BaseController } from "./BaseController";
import { parse } from "query-string";
import { adminApi } from "../Services/AdminApi";
import { ADMIN_API_URL, DISABLE_ANONYMOUS } from "../Enum/EnvironmentVariable";
import { GameRoomPolicyTypes } from "../Model/PusherRoom";
import { isMapDetailsData, MapDetailsData } from "../Services/AdminApi/MapDetailsData";
import { socketManager } from "../Services/SocketManager";
import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager";
import { v4 } from "uuid";
export class MapController extends BaseController {
constructor(private App: TemplatedApp) {
super();
this.App = App;
this.getMapUrl();
this.getWorlds();
}
// Returns a map mapping map name to file name of the map
getMapUrl() {
this.App.options("/map", (res: HttpResponse, req: HttpRequest) => {
this.addCorsHeaders(res);
res.end();
});
this.App.get("/map", (res: HttpResponse, req: HttpRequest) => {
res.onAborted(() => {
console.warn("/map request was aborted");
});
const query = parse(req.getQuery());
if (typeof query.playUri !== "string") {
console.error("Expected playUri parameter in /map endpoint");
res.writeStatus("400 Bad request");
this.addCorsHeaders(res);
res.end("Expected playUri parameter");
return;
}
// If no admin URL is set, let's react on '/_/[instance]/[map url]' URLs
if (!ADMIN_API_URL) {
const roomUrl = new URL(query.playUri);
const match = /\/_\/[^/]+\/(.+)/.exec(roomUrl.pathname);
if (!match) {
res.writeStatus("404 Not Found");
this.addCorsHeaders(res);
res.end(JSON.stringify({}));
return;
}
const mapUrl = roomUrl.protocol + "//" + match[ 1 ];
res.writeStatus("200 OK");
this.addCorsHeaders(res);
res.end(
JSON.stringify({
mapUrl,
policy_type: GameRoomPolicyTypes.ANONYMOUS_POLICY,
roomSlug: "", // Deprecated
group: null,
tags: [],
textures: [],
contactPage: undefined,
authenticationMandatory : DISABLE_ANONYMOUS,
} as MapDetailsData)
);
return;
}
(async () => {
try {
let userId: string | undefined = undefined;
if (query.authToken != undefined) {
let authTokenData: AuthTokenData;
try {
authTokenData = jwtTokenManager.verifyJWTToken(query.authToken as string);
userId = authTokenData.identifier;
} catch (e) {
// Decode token, in this case we don't need to create new token.
authTokenData = jwtTokenManager.verifyJWTToken(query.authToken as string, true);
userId = authTokenData.identifier;
console.info("JWT expire, but decoded", userId);
}
}
const mapDetails = await adminApi.fetchMapDetails(query.playUri as string, userId);
if (isMapDetailsData(mapDetails) && DISABLE_ANONYMOUS) {
(mapDetails as MapDetailsData).authenticationMandatory = true;
}
res.writeStatus("200 OK");
this.addCorsHeaders(res);
res.end(JSON.stringify(mapDetails));
} catch (e) {
this.errorToResponse(e, res);
}
})();
});
}
getWorlds() {
this.App.options("/worlds", (res: HttpResponse, req: HttpRequest) => {
this.addCorsHeaders(res);
res.end();
});
this.App.get("/worlds", async (res: HttpResponse, req: HttpRequest) => {
res.onAborted(() => {
console.warn("/message request was aborted");
});
const { token } = parse(req.getQuery());
try {
//verify connected by token
if (token != undefined) {
try {
jwtTokenManager.verifyJWTToken(token as string, false);
const result: any[] = [];
for (const room of socketManager.getWorlds().values()) {
const world: any = {};
world.roomId = room.roomUrl;
world.player = [];
for (const listener of room.getListeners()) {
const position: any = {};
position.name = listener.name;
position.roomId = listener.roomId;
position.position = listener.position;
position.viewport = listener.viewport;
world.player.push(listener.name);
}
result.push(world);
}
res.writeStatus("200 OK");
res.writeHeader("Content-Type", "application/json");
this.addCorsHeaders(res);
res.end(
JSON.stringify({ worlds: result })
);
} catch (error) {
res.writeStatus("403 FORBIDDEN");
this.addCorsHeaders(res);
res.end();
}
} else {
res.writeStatus("401 UNAUTHORIZED");
this.addCorsHeaders(res);
res.end();
}
} catch (error) {
console.error("getWorlds => ERROR", error);
this.errorToResponse(error, res);
}
});
}
}