Migrating away from the notion of public/private URL in WorkAdventure Github repository

The notion of public/private repositories (with /_/ and /@/ URLs) is specific to the SAAS version of WorkAdventure.
It would be better to avoid leaking the organization/world/room structure of the private SAAS URLs inside the WorkAdventure Github project.

Rather than sending http://admin_host/api/map?organizationSlug=...&worldSlug=...&roomSlug=...., we are now sending /api/map&playUri=...
where playUri is the full URL of the current game.
This allows the backend to act as a complete router.
The front (and the pusher) will be able to completely ignore the specifics of URL building (with /@/ and /_/ URLs, etc...)
Those details will live only in the admin server, which is way cleaner (and way more powerful).
This commit is contained in:
David Négrier 2021-07-13 19:09:07 +02:00
parent f2ca7b2b16
commit c9fa9b9a92
20 changed files with 292 additions and 343 deletions

View file

@ -39,9 +39,7 @@ export class AuthenticateController extends BaseController {
if (typeof organizationMemberToken != "string") throw new Error("No organization token");
const data = await adminApi.fetchMemberDataByToken(organizationMemberToken);
const userUuid = data.userUuid;
const organizationSlug = data.organizationSlug;
const worldSlug = data.worldSlug;
const roomSlug = data.roomSlug;
const roomUrl = data.roomUrl;
const mapUrlStart = data.mapUrlStart;
const textures = data.textures;
@ -52,9 +50,7 @@ export class AuthenticateController extends BaseController {
JSON.stringify({
authToken,
userUuid,
organizationSlug,
worldSlug,
roomSlug,
roomUrl,
mapUrlStart,
organizationMemberToken,
textures,

View file

@ -221,14 +221,12 @@ export class IoSocketController {
memberVisitCardUrl = userData.visitCardUrl;
memberTextures = userData.textures;
if (
!room.public &&
room.policyType === GameRoomPolicyTypes.USE_TAGS_POLICY &&
(userData.anonymous === true || !room.canAccess(memberTags))
) {
throw new Error("Insufficient privileges to access this room");
}
if (
!room.public &&
room.policyType === GameRoomPolicyTypes.MEMBERS_ONLY_POLICY &&
userData.anonymous === true
) {

View file

@ -1,7 +1,9 @@
import { HttpRequest, HttpResponse, TemplatedApp } from "uWebSockets.js";
import { BaseController } from "./BaseController";
import { parse } from "query-string";
import { adminApi } from "../Services/AdminApi";
import { adminApi, MapDetailsData } from "../Services/AdminApi";
import { ADMIN_API_URL } from "../Enum/EnvironmentVariable";
import { GameRoomPolicyTypes } from "../Model/PusherRoom";
export class MapController extends BaseController {
constructor(private App: TemplatedApp) {
@ -25,35 +27,45 @@ export class MapController extends BaseController {
const query = parse(req.getQuery());
if (typeof query.organizationSlug !== "string") {
console.error("Expected organizationSlug parameter");
if (typeof query.playUri !== "string") {
console.error("Expected playUri parameter in /map endpoint");
res.writeStatus("400 Bad request");
this.addCorsHeaders(res);
res.end("Expected organizationSlug parameter");
res.end("Expected playUri parameter");
return;
}
if (typeof query.worldSlug !== "string") {
console.error("Expected worldSlug parameter");
res.writeStatus("400 Bad request");
// 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("Expected worldSlug parameter");
return;
}
if (typeof query.roomSlug !== "string" && query.roomSlug !== undefined) {
console.error("Expected only one roomSlug parameter");
res.writeStatus("400 Bad request");
this.addCorsHeaders(res);
res.end("Expected only one roomSlug parameter");
res.end(
JSON.stringify({
mapUrl,
policy_type: GameRoomPolicyTypes.ANONYMOUS_POLICY,
roomSlug: "", // Deprecated
tags: [],
} as MapDetailsData)
);
return;
}
(async () => {
try {
const mapDetails = await adminApi.fetchMapDetails(
query.organizationSlug as string,
query.worldSlug as string,
query.roomSlug as string | undefined
);
const mapDetails = await adminApi.fetchMapDetails(query.playUri as string);
res.writeStatus("200 OK");
this.addCorsHeaders(res);