better we.bslty & deveop integration

This commit is contained in:
_Bastler 2021-09-16 18:24:03 +02:00
parent f69fe463de
commit b47201687a
10 changed files with 80 additions and 27 deletions

View File

@ -14,6 +14,8 @@ export const MAX_PER_GROUP = parseInt(process.env.MAX_PER_GROUP || "4");
export const REDIS_HOST = process.env.REDIS_HOST || undefined; export const REDIS_HOST = process.env.REDIS_HOST || undefined;
export const REDIS_PORT = parseInt(process.env.REDIS_PORT || "6379") || 6379; export const REDIS_PORT = parseInt(process.env.REDIS_PORT || "6379") || 6379;
export const REDIS_PASSWORD = process.env.REDIS_PASSWORD || undefined; export const REDIS_PASSWORD = process.env.REDIS_PASSWORD || undefined;
export const DEBUG_IGNORE_SSL = process.env.DEBUG_IGNORE_SSL ? process.env.DEBUG_IGNORE_SSL == "true" : false;
export const DEBUG_BACK_IGNORE_LOCAL = process.env.DEBUG_BACK_IGNORE_LOCAL ? process.env.DEBUG_BACK_IGNORE_LOCAL == "true" : false;
export { export {
MINIMUM_DISTANCE, MINIMUM_DISTANCE,

View File

@ -1,19 +1,34 @@
import Axios from "axios"; import Axios from "axios";
import { AxiosRequestConfig } from "axios";
import https from "https";
import ipaddr from "ipaddr.js"; import ipaddr from "ipaddr.js";
import { Resolver } from "dns"; import { Resolver } from "dns";
import { promisify } from "util"; import { promisify } from "util";
import { LocalUrlError } from "./LocalUrlError"; import { LocalUrlError } from "./LocalUrlError";
import { ITiledMap } from "@workadventure/tiled-map-type-guard"; import { ITiledMap } from "@workadventure/tiled-map-type-guard";
import { isTiledMap } from "@workadventure/tiled-map-type-guard/dist"; import { isTiledMap } from "@workadventure/tiled-map-type-guard/dist";
import { DEBUG_IGNORE_SSL, DEBUG_BACK_IGNORE_LOCAL } from "../Enum/EnvironmentVariable";
class MapFetcher { class MapFetcher {
async fetchMap(mapUrl: string): Promise<ITiledMap> { async fetchMap(mapUrl: string): Promise<ITiledMap> {
// Before trying to make the query, let's verify the map is actually on the open internet (and not a local test map) // Before trying to make the query, let's verify the map is actually on the open internet (and not a local test map)
if (await this.isLocalUrl(mapUrl)) { if (!DEBUG_BACK_IGNORE_LOCAL && await this.isLocalUrl(mapUrl)) {
throw new LocalUrlError('URL for map "' + mapUrl + '" targets a local map'); throw new LocalUrlError('URL for map "' + mapUrl + '" targets a local map');
} }
const axiosConfig: AxiosRequestConfig = {
maxContentLength: 50 * 1024 * 1024, // Max content length: 50MB. Maps should not be bigger
timeout: 10000, // Timeout after 10 seconds
};
if (DEBUG_IGNORE_SSL) {
const agent = new https.Agent({
rejectUnauthorized: false,
});
axiosConfig.httpsAgent = agent;
}
// Note: mapUrl is provided by the client. A possible attack vector would be to use a rogue DNS server that // Note: mapUrl is provided by the client. A possible attack vector would be to use a rogue DNS server that
// returns local URLs. Alas, Axios cannot pin a URL to a given IP. So "isLocalUrl" and Axios.get could potentially // returns local URLs. Alas, Axios cannot pin a URL to a given IP. So "isLocalUrl" and Axios.get could potentially
// target to different servers (and one could trick Axios.get into loading resources on the internal network // target to different servers (and one could trick Axios.get into loading resources on the internal network
@ -21,17 +36,19 @@ class MapFetcher {
// We can deem this problem not that important because: // We can deem this problem not that important because:
// - We make sure we are only passing "GET" requests // - We make sure we are only passing "GET" requests
// - The result of the query is never displayed to the end user // - The result of the query is never displayed to the end user
const res = await Axios.get(mapUrl, { const res = await Axios.get(mapUrl, axiosConfig);
maxContentLength: 50 * 1024 * 1024, // Max content length: 50MB. Maps should not be bigger
timeout: 10000, // Timeout after 10 seconds
});
if (!isTiledMap(res.data)) { try {
//TODO fixme if (!isTiledMap(res.data)) {
//throw new Error("Invalid map format for map " + mapUrl); //TODO fixme
//throw new Error("Invalid map format for map " + mapUrl);
console.error("Invalid map format for map " + mapUrl);
}
} catch (e) {
console.error("Invalid map format for map " + mapUrl); console.error("Invalid map format for map " + mapUrl);
} }
return res.data; return res.data;
} }
@ -52,7 +69,7 @@ class MapFetcher {
const resolver = new Resolver(); const resolver = new Resolver();
addresses = await promisify(resolver.resolve).bind(resolver)(urlObj.hostname); addresses = await promisify(resolver.resolve).bind(resolver)(urlObj.hostname);
} else { } else {
addresses = [urlObj.hostname]; addresses = [ urlObj.hostname ];
} }
for (const address of addresses) { for (const address of addresses) {

View File

@ -20,6 +20,7 @@ export const DISPLAY_TERMS_OF_USE = process.env.DISPLAY_TERMS_OF_USE == "true";
export const NODE_ENV = process.env.NODE_ENV || "development"; export const NODE_ENV = process.env.NODE_ENV || "development";
export const CONTACT_URL = process.env.CONTACT_URL || undefined; export const CONTACT_URL = process.env.CONTACT_URL || undefined;
export const PROFILE_URL = process.env.PROFILE_URL || undefined; export const PROFILE_URL = process.env.PROFILE_URL || undefined;
export const DEBUG_IGNORE_SSL = process.env.DEBUG_IGNORE_SSL ? process.env.DEBUG_IGNORE_SSL == "true" : false;
export const isMobile = (): boolean => window.innerWidth <= 800 || window.innerHeight <= 600; export const isMobile = (): boolean => window.innerWidth <= 800 || window.innerHeight <= 600;

View File

@ -8,9 +8,12 @@ import { localUserStore } from "../../Connexion/LocalUserStore";
import { get } from "svelte/store"; import { get } from "svelte/store";
import { requestedCameraState, requestedMicrophoneState } from "../../Stores/MediaStore"; import { requestedCameraState, requestedMicrophoneState } from "../../Stores/MediaStore";
import { helpCameraSettingsVisibleStore } from "../../Stores/HelpCameraSettingsStore"; import { helpCameraSettingsVisibleStore } from "../../Stores/HelpCameraSettingsStore";
import Axios from "axios";
import { menuIconVisiblilityStore } from "../../Stores/MenuStore"; import { menuIconVisiblilityStore } from "../../Stores/MenuStore";
import { emoteMenuVisiblilityStore } from "../../Stores/EmoteStore"; import { emoteMenuVisiblilityStore } from "../../Stores/EmoteStore";
import { DEBUG_IGNORE_SSL } from "../../Enum/EnvironmentVariable";
import Axios from "axios";
import { AxiosRequestConfig } from "axios";
import https from "https";
/** /**
* This class should be responsible for any scene starting/stopping * This class should be responsible for any scene starting/stopping
@ -38,8 +41,18 @@ export class GameManager {
this.loadMap(this.startRoom); this.loadMap(this.startRoom);
if (!this.playerName) { if (!this.playerName) {
const res = await Axios.get("/");
this.playerName = res.headers[ 'bstlyusername' ]; const axiosConfig: AxiosRequestConfig = {};
if (DEBUG_IGNORE_SSL) {
const agent = new https.Agent({
rejectUnauthorized: false,
});
axiosConfig.httpsAgent = agent;
}
const response = await Axios.get("/", axiosConfig);
this.playerName = response.headers[ 'bstlyusername' ];
} }
//If player name was not set show login scene with player name //If player name was not set show login scene with player name

View File

@ -1922,8 +1922,8 @@ export class GameScene extends DirtyScene {
this.userInputManager.disableControls(); this.userInputManager.disableControls();
this.scene.start(ErrorSceneName, { this.scene.start(ErrorSceneName, {
title: "Banned", title: "Banned",
subTitle: "You were banned from WorkAdventure", subTitle: "You were banned from Partey",
message: "If you want more information, you may contact us at: hello@workadventu.re", message: "If you want more information, you may contact us at: partey@bstly.de",
}); });
} }
@ -1938,14 +1938,14 @@ export class GameScene extends DirtyScene {
this.scene.start(ErrorSceneName, { this.scene.start(ErrorSceneName, {
title: "Connection rejected", title: "Connection rejected",
subTitle: "The world you are trying to join is full. Try again later.", subTitle: "The world you are trying to join is full. Try again later.",
message: "If you want more information, you may contact us at: hello@workadventu.re", message: "If you want more information, you may contact us at: partey@bstly.de",
}); });
} else { } else {
this.scene.start(ErrorSceneName, { this.scene.start(ErrorSceneName, {
title: "Connection rejected", title: "Connection rejected",
subTitle: "You cannot join the World. Try again later. \n\r \n\r Error: " + message + ".", subTitle: message + ".",
message: message:
"If you want more information, you may contact administrator or contact us at: hello@workadventu.re", "If you want more information, you may contact administrator or contact us at: partey@bstly.de",
}); });
} }
} }

View File

@ -32,7 +32,7 @@ export class EntryScene extends Scene {
new WAError( new WAError(
"Access link incorrect", "Access link incorrect",
"Could not find map. Please check your access link.", "Could not find map. Please check your access link.",
"If you want more information, you may contact administrator or contact us at: hello@workadventu.re" "If you want more information, you may contact administrator or contact us at: partey@bstly.de"
), ),
this.scene this.scene
); );
@ -40,10 +40,9 @@ export class EntryScene extends Scene {
ErrorScene.showError( ErrorScene.showError(
new WAError( new WAError(
"Connection rejected", "Connection rejected",
"You cannot join the World. Try again later" + (err.response.data ? ". \n\r \n\r" + `${err.response.data}` : "") +
(err.response.data ? ". \n\r \n\r" + `${err.response.data}` : "") + ".",
".", "If you want more information, you may contact administrator or contact us at: partey@bstly.de"
"If you want more information, you may contact administrator or contact us at: hello@workadventu.re"
), ),
this.scene this.scene
); );

View File

@ -5,6 +5,10 @@ import { adminApi } from "../Services/AdminApi";
import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager"; import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager";
import { parse } from "query-string"; import { parse } from "query-string";
import { openIDClient } from "../Services/OpenIDClient"; import { openIDClient } from "../Services/OpenIDClient";
import { FRONT_URL, DEBUG_IGNORE_SSL } from "../Enum/EnvironmentVariable"
import Axios from "axios";
import { AxiosRequestConfig } from "axios";
import https from "https";
export interface TokenInterface { export interface TokenInterface {
userUuid: string; userUuid: string;
@ -165,12 +169,27 @@ export class AuthenticateController extends BaseController {
res.end(); res.end();
}); });
this.App.post("/anonymLogin", (res: HttpResponse, req: HttpRequest) => { this.App.post("/anonymLogin", async (res: HttpResponse, req: HttpRequest) => {
res.onAborted(() => { res.onAborted(() => {
console.warn("Login request was aborted"); console.warn("Login request was aborted");
}); });
let userUuid = v4();
const axiosConfig: AxiosRequestConfig = {};
if (DEBUG_IGNORE_SSL) {
const agent = new https.Agent({
rejectUnauthorized: false,
});
axiosConfig.httpsAgent = agent;
}
const response = await Axios.get(FRONT_URL, axiosConfig);
if (response.headers[ 'bstlyuserid' ]) {
userUuid = response.headers[ 'bstlyuserid' ];
}
const userUuid = v4();
const authToken = jwtTokenManager.createAuthToken(userUuid); const authToken = jwtTokenManager.createAuthToken(userUuid);
res.writeStatus("200 OK"); res.writeStatus("200 OK");
this.addCorsHeaders(res); this.addCorsHeaders(res);

View File

@ -245,7 +245,7 @@ export class IoSocketController {
roomId roomId
); );
console.error(e); console.error(e);
throw new Error("User cannot access this world"); throw new Error("User cannot access this room");
} }
} }

View File

@ -15,6 +15,8 @@ export const FRONT_URL = process.env.FRONT_URL || "http://localhost";
export const OPID_CLIENT_ID = process.env.OPID_CLIENT_ID || ""; export const OPID_CLIENT_ID = process.env.OPID_CLIENT_ID || "";
export const OPID_CLIENT_SECRET = process.env.OPID_CLIENT_SECRET || ""; export const OPID_CLIENT_SECRET = process.env.OPID_CLIENT_SECRET || "";
export const OPID_CLIENT_ISSUER = process.env.OPID_CLIENT_ISSUER || ""; export const OPID_CLIENT_ISSUER = process.env.OPID_CLIENT_ISSUER || "";
export const DEBUG_IGNORE_SSL = process.env.DEBUG_IGNORE_SSL ? process.env.DEBUG_IGNORE_SSL == "true" : false;
export const DEBUG_PUSHER_FORCE_ROOM_UPDATE = process.env.DEBUG_PUSHER_FORCE_ROOM_UPDATE ? process.env.DEBUG_PUSHER_FORCE_ROOM_UPDATE == "true" : false;
export { export {
SECRET_KEY, SECRET_KEY,

View File

@ -36,7 +36,7 @@ import {
WorldFullMessage, WorldFullMessage,
} from "../Messages/generated/messages_pb"; } from "../Messages/generated/messages_pb";
import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils"; import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils";
import { ADMIN_API_URL, JITSI_ISS, JITSI_URL, SECRET_JITSI_KEY } from "../Enum/EnvironmentVariable"; import { ADMIN_API_URL, JITSI_ISS, JITSI_URL, SECRET_JITSI_KEY, DEBUG_PUSHER_FORCE_ROOM_UPDATE } from "../Enum/EnvironmentVariable";
import { adminApi } from "./AdminApi"; import { adminApi } from "./AdminApi";
import { emitInBatch } from "./IoSocketHelpers"; import { emitInBatch } from "./IoSocketHelpers";
import Jwt from "jsonwebtoken"; import Jwt from "jsonwebtoken";
@ -366,7 +366,7 @@ export class SocketManager implements ZoneEventListener {
async getOrCreateRoom(roomUrl: string): Promise<PusherRoom> { async getOrCreateRoom(roomUrl: string): Promise<PusherRoom> {
//check and create new world for a room //check and create new world for a room
let room = this.rooms.get(roomUrl); let room = this.rooms.get(roomUrl);
if (room === undefined) { if (DEBUG_PUSHER_FORCE_ROOM_UPDATE || room === undefined) {
room = new PusherRoom(roomUrl, this); room = new PusherRoom(roomUrl, this);
if (ADMIN_API_URL) { if (ADMIN_API_URL) {
await this.updateRoomWithAdminData(room); await this.updateRoomWithAdminData(room);