secure DISABLE_ANONYMOUS
This commit is contained in:
parent
e3470d3474
commit
f984897e80
@ -14,7 +14,6 @@ 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 const DEBUG_BACK_IGNORE_LOCAL = process.env.DEBUG_BACK_IGNORE_LOCAL ? process.env.DEBUG_BACK_IGNORE_LOCAL == "true" : false;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
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";
|
import { DEBUG_BACK_IGNORE_LOCAL } from "../Enum/EnvironmentVariable";
|
||||||
|
|
||||||
class MapFetcher {
|
class MapFetcher {
|
||||||
async fetchMap(mapUrl: string): Promise<ITiledMap> {
|
async fetchMap(mapUrl: string): Promise<ITiledMap> {
|
||||||
@ -17,18 +15,6 @@ class MapFetcher {
|
|||||||
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
|
||||||
@ -36,18 +22,16 @@ 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, axiosConfig);
|
const res = await Axios.get(mapUrl, {
|
||||||
|
maxContentLength: 50 * 1024 * 1024, // Max content length: 50MB. Maps should not be bigger
|
||||||
|
timeout: 10000, // Timeout after 10 seconds
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
|
||||||
if (!isTiledMap(res.data)) {
|
if (!isTiledMap(res.data)) {
|
||||||
//TODO fixme
|
//TODO fixme
|
||||||
//throw new Error("Invalid map format for map " + mapUrl);
|
//throw new Error("Invalid map format for map " + mapUrl);
|
||||||
console.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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
@ -44,13 +44,22 @@ class ConnectionManager {
|
|||||||
|
|
||||||
//TODO fix me to redirect this URL by pusher
|
//TODO fix me to redirect this URL by pusher
|
||||||
if (!this._currentRoom) {
|
if (!this._currentRoom) {
|
||||||
console.error("cannot get currentRoom!");
|
|
||||||
loginSceneVisibleIframeStore.set(false);
|
loginSceneVisibleIframeStore.set(false);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const redirectUrl = `${PUSHER_URL}/login-screen?state=${state}&nonce=${nonce}&playUri=${this._currentRoom.key}`;
|
// also allow OIDC login without admin API by using pusher
|
||||||
window.location.assign(redirectUrl);
|
let redirectUrl : URL;
|
||||||
|
if (this._currentRoom.iframeAuthentication) {
|
||||||
|
redirectUrl = new URL(`${this._currentRoom.iframeAuthentication}`);
|
||||||
|
} else {
|
||||||
|
// need origin if PUSHER_URL is relative (in Single-Domain-Deployment)
|
||||||
|
redirectUrl = new URL(`${PUSHER_URL}/login-screen`, (!PUSHER_URL.startsWith('http:') || !PUSHER_URL.startsWith('https:')) ? window.location.origin : undefined);
|
||||||
|
}
|
||||||
|
redirectUrl.searchParams.append("state", state);
|
||||||
|
redirectUrl.searchParams.append("nonce", nonce);
|
||||||
|
redirectUrl.searchParams.append("playUri", this._currentRoom.key);
|
||||||
|
window.location.assign(redirectUrl.toString());
|
||||||
return redirectUrl;
|
return redirectUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ export class Room {
|
|||||||
private _iframeAuthentication?: string;
|
private _iframeAuthentication?: string;
|
||||||
private _mapUrl: string | undefined;
|
private _mapUrl: string | undefined;
|
||||||
private _textures: CharacterTexture[] | undefined;
|
private _textures: CharacterTexture[] | undefined;
|
||||||
// private instance: string | undefined;
|
private instance: string | undefined;
|
||||||
private readonly _search: URLSearchParams;
|
private readonly _search: URLSearchParams;
|
||||||
private _contactPage: string | undefined;
|
private _contactPage: string | undefined;
|
||||||
private _group: string | null = null;
|
private _group: string | null = null;
|
||||||
@ -75,13 +75,12 @@ export class Room {
|
|||||||
const baseUrl = new URL(currentRoomUrl);
|
const baseUrl = new URL(currentRoomUrl);
|
||||||
|
|
||||||
const currentRoom = new Room(baseUrl);
|
const currentRoom = new Room(baseUrl);
|
||||||
// let instance: string = "global";
|
let instance: string = "global";
|
||||||
// if (currentRoom.isPublic) {
|
if (currentRoom.isPublic) {
|
||||||
// instance = currentRoom.instance as string;
|
instance = currentRoom.instance as string;
|
||||||
//}
|
}
|
||||||
|
|
||||||
// baseUrl.pathname = "/_/" + instance + "/" + absoluteExitSceneUrl.host + absoluteExitSceneUrl.pathname;
|
baseUrl.pathname = "/_/" + instance + "/" + absoluteExitSceneUrl.host + absoluteExitSceneUrl.pathname;
|
||||||
baseUrl.pathname = "/_/" + absoluteExitSceneUrl.host + absoluteExitSceneUrl.pathname;
|
|
||||||
if (absoluteExitSceneUrl.hash) {
|
if (absoluteExitSceneUrl.hash) {
|
||||||
baseUrl.hash = absoluteExitSceneUrl.hash;
|
baseUrl.hash = absoluteExitSceneUrl.hash;
|
||||||
}
|
}
|
||||||
@ -119,8 +118,6 @@ export class Room {
|
|||||||
* - In a private URL: [organizationId/worldId]
|
* - In a private URL: [organizationId/worldId]
|
||||||
*/
|
*/
|
||||||
public getInstance(): string {
|
public getInstance(): string {
|
||||||
return "";
|
|
||||||
/*
|
|
||||||
if (this.instance !== undefined) {
|
if (this.instance !== undefined) {
|
||||||
return this.instance;
|
return this.instance;
|
||||||
}
|
}
|
||||||
@ -131,12 +128,12 @@ export class Room {
|
|||||||
this.instance = match[1];
|
this.instance = match[1];
|
||||||
return this.instance;
|
return this.instance;
|
||||||
} else {
|
} else {
|
||||||
const match = /@\/([^/]+)\/([^/]+)\/.+/.exec(this.id);
|
//const match = /@\/([^/]+)\/([^/]+)\/.+/.exec(this.id);
|
||||||
if (!match) throw new Error('Could not extract instance from "' + this.id + '"');
|
//if (!match) throw new Error('Could not extract instance from "' + this.id + '"');
|
||||||
this.instance = match[1] + "/" + match[2];
|
//this.instance = match[1] + "/" + match[2];
|
||||||
|
this.instance = ""
|
||||||
return this.instance;
|
return this.instance;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public isDisconnected(): boolean {
|
public isDisconnected(): boolean {
|
||||||
|
@ -37,7 +37,7 @@ export class GameManager {
|
|||||||
|
|
||||||
//If player name was not set show login scene with player name
|
//If player name was not set show login scene with player name
|
||||||
//If Room si not public and Auth was not set, show login scene to authenticate user (OpenID - SSO - Anonymous)
|
//If Room si not public and Auth was not set, show login scene to authenticate user (OpenID - SSO - Anonymous)
|
||||||
if (!this.playerName || !localUserStore.getAuthToken()) {
|
if (!this.playerName || (this.startRoom.authenticationMandatory && !localUserStore.getAuthToken())) {
|
||||||
return LoginSceneName;
|
return LoginSceneName;
|
||||||
} else if (!this.characterLayers || !this.characterLayers.length) {
|
} else if (!this.characterLayers || !this.characterLayers.length) {
|
||||||
return SelectCharacterSceneName;
|
return SelectCharacterSceneName;
|
||||||
|
@ -303,17 +303,12 @@ export class GameScene extends DirtyScene {
|
|||||||
//remove loader in progress
|
//remove loader in progress
|
||||||
removeLoader(this);
|
removeLoader(this);
|
||||||
|
|
||||||
if (this.roomUrl == localUserStore.getLastRoomUrl()) {
|
|
||||||
localUserStore.setLastRoomUrl(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
//display an error scene
|
//display an error scene
|
||||||
this.scene.start(ErrorSceneName, {
|
this.scene.start(ErrorSceneName, {
|
||||||
title: "Network error",
|
title: "Network error",
|
||||||
subTitle: "An error occurred while loading resource:",
|
subTitle: "An error occurred while loading resource:",
|
||||||
message: this.originalMapUrl ?? file.src,
|
message: this.originalMapUrl ?? file.src,
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.load.scenePlugin("AnimatedTiles", AnimatedTiles, "animatedTiles", "animatedTiles");
|
this.load.scenePlugin("AnimatedTiles", AnimatedTiles, "animatedTiles", "animatedTiles");
|
||||||
@ -460,12 +455,6 @@ export class GameScene extends DirtyScene {
|
|||||||
//initialise map
|
//initialise map
|
||||||
this.Map = this.add.tilemap(this.MapUrlFile);
|
this.Map = this.add.tilemap(this.MapUrlFile);
|
||||||
const mapDirUrl = this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf("/"));
|
const mapDirUrl = this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf("/"));
|
||||||
|
|
||||||
if (!this.mapFile) {
|
|
||||||
localUserStore.setLastRoomUrl(null);
|
|
||||||
throw new Error("invalid map");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.mapFile.tilesets.forEach((tileset: ITiledTileSet) => {
|
this.mapFile.tilesets.forEach((tileset: ITiledTileSet) => {
|
||||||
this.Terrains.push(
|
this.Terrains.push(
|
||||||
this.Map.addTilesetImage(
|
this.Map.addTilesetImage(
|
||||||
|
@ -23,7 +23,9 @@ export class LoginScene extends ResizableScene {
|
|||||||
loginSceneVisibleIframeStore.set(false);
|
loginSceneVisibleIframeStore.set(false);
|
||||||
//If authentication is mandatory, push authentication iframe
|
//If authentication is mandatory, push authentication iframe
|
||||||
if (
|
if (
|
||||||
localUserStore.getAuthToken() == undefined
|
localUserStore.getAuthToken() == undefined &&
|
||||||
|
gameManager.currentStartedRoom &&
|
||||||
|
gameManager.currentStartedRoom.authenticationMandatory
|
||||||
) {
|
) {
|
||||||
connectionManager.loadOpenIDScreen();
|
connectionManager.loadOpenIDScreen();
|
||||||
loginSceneVisibleIframeStore.set(true);
|
loginSceneVisibleIframeStore.set(true);
|
||||||
|
@ -38,7 +38,7 @@ class UrlManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public pushRoomIdToUrl(room: Room): void {
|
public pushRoomIdToUrl(room: Room): void {
|
||||||
if (window.location.pathname === room.id || room.isPublic) return;
|
if (window.location.pathname === room.id) return;
|
||||||
//Set last room visited! (connected or nor, must to be saved in localstorage and cache API)
|
//Set last room visited! (connected or nor, must to be saved in localstorage and cache API)
|
||||||
localUserStore.setLastRoomUrl(room.key);
|
localUserStore.setLastRoomUrl(room.key);
|
||||||
const hash = window.location.hash;
|
const hash = window.location.hash;
|
||||||
|
@ -5,9 +5,7 @@ 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 { DEBUG_IGNORE_SSL, PUSHER_DISABLE_ANONYMOUS } from "../Enum/EnvironmentVariable"
|
import { DISABLE_ANONYMOUS } from "../Enum/EnvironmentVariable"
|
||||||
import { AxiosRequestConfig } from "axios";
|
|
||||||
import https from "https";
|
|
||||||
|
|
||||||
export interface TokenInterface {
|
export interface TokenInterface {
|
||||||
userUuid: string;
|
userUuid: string;
|
||||||
@ -173,26 +171,16 @@ export class AuthenticateController extends BaseController {
|
|||||||
res.end();
|
res.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.App.post("/anonymLogin", async (res: HttpResponse, req: HttpRequest) => {
|
this.App.post("/anonymLogin", (res: HttpResponse, req: HttpRequest) => {
|
||||||
res.onAborted(() => {
|
res.onAborted(() => {
|
||||||
console.warn("Login request was aborted");
|
console.warn("Login request was aborted");
|
||||||
});
|
});
|
||||||
|
|
||||||
if (PUSHER_DISABLE_ANONYMOUS) {
|
if (DISABLE_ANONYMOUS) {
|
||||||
res.writeStatus("403 FORBIDDEN");
|
res.writeStatus("403 FORBIDDEN");
|
||||||
res.end();
|
res.end();
|
||||||
} else {
|
} else {
|
||||||
let userUuid = v4();
|
const userUuid = v4();
|
||||||
|
|
||||||
const axiosConfig: AxiosRequestConfig = {};
|
|
||||||
|
|
||||||
if (DEBUG_IGNORE_SSL) {
|
|
||||||
const agent = new https.Agent({
|
|
||||||
rejectUnauthorized: false,
|
|
||||||
});
|
|
||||||
axiosConfig.httpsAgent = agent;
|
|
||||||
}
|
|
||||||
|
|
||||||
const authToken = jwtTokenManager.createAuthToken(userUuid);
|
const authToken = jwtTokenManager.createAuthToken(userUuid);
|
||||||
res.writeStatus("200 OK");
|
res.writeStatus("200 OK");
|
||||||
this.addCorsHeaders(res);
|
this.addCorsHeaders(res);
|
||||||
|
@ -26,7 +26,7 @@ import { jwtTokenManager, tokenInvalidException } from "../Services/JWTTokenMana
|
|||||||
import { adminApi, FetchMemberDataByUuidResponse } from "../Services/AdminApi";
|
import { adminApi, FetchMemberDataByUuidResponse } from "../Services/AdminApi";
|
||||||
import { SocketManager, socketManager } from "../Services/SocketManager";
|
import { SocketManager, socketManager } from "../Services/SocketManager";
|
||||||
import { emitInBatch } from "../Services/IoSocketHelpers";
|
import { emitInBatch } from "../Services/IoSocketHelpers";
|
||||||
import { ADMIN_API_TOKEN, ADMIN_API_URL, SOCKET_IDLE_TIMER } from "../Enum/EnvironmentVariable";
|
import { ADMIN_API_TOKEN, ADMIN_API_URL, SOCKET_IDLE_TIMER, DISABLE_ANONYMOUS } from "../Enum/EnvironmentVariable";
|
||||||
import { Zone } from "_Model/Zone";
|
import { Zone } from "_Model/Zone";
|
||||||
import { ExAdminSocketInterface } from "_Model/Websocket/ExAdminSocketInterface";
|
import { ExAdminSocketInterface } from "_Model/Websocket/ExAdminSocketInterface";
|
||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
@ -175,6 +175,11 @@ export class IoSocketController {
|
|||||||
|
|
||||||
const tokenData =
|
const tokenData =
|
||||||
token && typeof token === "string" ? jwtTokenManager.verifyJWTToken(token) : null;
|
token && typeof token === "string" ? jwtTokenManager.verifyJWTToken(token) : null;
|
||||||
|
|
||||||
|
if (DISABLE_ANONYMOUS && !tokenData) {
|
||||||
|
throw new Error("Expecting token");
|
||||||
|
}
|
||||||
|
|
||||||
const userIdentifier = tokenData ? tokenData.identifier : "";
|
const userIdentifier = tokenData ? tokenData.identifier : "";
|
||||||
|
|
||||||
let memberTags: string[] = [];
|
let memberTags: string[] = [];
|
||||||
|
@ -2,9 +2,9 @@ import { HttpRequest, HttpResponse, TemplatedApp } from "uWebSockets.js";
|
|||||||
import { BaseController } from "./BaseController";
|
import { BaseController } from "./BaseController";
|
||||||
import { parse } from "query-string";
|
import { parse } from "query-string";
|
||||||
import { adminApi } from "../Services/AdminApi";
|
import { adminApi } from "../Services/AdminApi";
|
||||||
import { ADMIN_API_URL } from "../Enum/EnvironmentVariable";
|
import { ADMIN_API_URL, DISABLE_ANONYMOUS } from "../Enum/EnvironmentVariable";
|
||||||
import { PusherRoom, GameRoomPolicyTypes } from "../Model/PusherRoom";
|
import { GameRoomPolicyTypes } from "../Model/PusherRoom";
|
||||||
import { MapDetailsData } from "../Services/AdminApi/MapDetailsData";
|
import { isMapDetailsData, MapDetailsData } from "../Services/AdminApi/MapDetailsData";
|
||||||
import { socketManager } from "../Services/SocketManager";
|
import { socketManager } from "../Services/SocketManager";
|
||||||
import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager";
|
import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager";
|
||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
@ -65,6 +65,7 @@ export class MapController extends BaseController {
|
|||||||
tags: [],
|
tags: [],
|
||||||
textures: [],
|
textures: [],
|
||||||
contactPage: undefined,
|
contactPage: undefined,
|
||||||
|
authenticationMandatory : DISABLE_ANONYMOUS,
|
||||||
} as MapDetailsData)
|
} as MapDetailsData)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -88,6 +89,10 @@ export class MapController extends BaseController {
|
|||||||
}
|
}
|
||||||
const mapDetails = await adminApi.fetchMapDetails(query.playUri as string, 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");
|
res.writeStatus("200 OK");
|
||||||
this.addCorsHeaders(res);
|
this.addCorsHeaders(res);
|
||||||
res.end(JSON.stringify(mapDetails));
|
res.end(JSON.stringify(mapDetails));
|
||||||
|
@ -12,12 +12,11 @@ const PUSHER_HTTP_PORT = parseInt(process.env.PUSHER_HTTP_PORT || "8080") || 808
|
|||||||
export const SOCKET_IDLE_TIMER = parseInt(process.env.SOCKET_IDLE_TIMER as string) || 120; // maximum time (in second) without activity before a socket is closed. Should be greater than 60 seconds in order to cope for Chrome intensive throttling (https://developer.chrome.com/blog/timer-throttling-in-chrome-88/#intensive-throttling)
|
export const SOCKET_IDLE_TIMER = parseInt(process.env.SOCKET_IDLE_TIMER as string) || 120; // maximum time (in second) without activity before a socket is closed. Should be greater than 60 seconds in order to cope for Chrome intensive throttling (https://developer.chrome.com/blog/timer-throttling-in-chrome-88/#intensive-throttling)
|
||||||
|
|
||||||
export const FRONT_URL = process.env.FRONT_URL || "http://localhost";
|
export const FRONT_URL = process.env.FRONT_URL || "http://localhost";
|
||||||
export const PUSHER_DISABLE_ANONYMOUS = process.env.PUSHER_DISABLE_ANONYMOUS ? process.env.PUSHER_DISABLE_ANONYMOUS == "true" : false;
|
export const DISABLE_ANONYMOUS = process.env.DISABLE_ANONYMOUS ? process.env.DISABLE_ANONYMOUS == "true" : false;
|
||||||
export const PUSHER_FORCE_ROOM_UPDATE = process.env.PUSHER_FORCE_ROOM_UPDATE ? process.env.PUSHER_FORCE_ROOM_UPDATE == "true" : false;
|
export const PUSHER_FORCE_ROOM_UPDATE = process.env.PUSHER_FORCE_ROOM_UPDATE ? process.env.PUSHER_FORCE_ROOM_UPDATE == "true" : false;
|
||||||
export const OIDC_CLIENT_ID = process.env.OIDC_CLIENT_ID || "";
|
export const OIDC_CLIENT_ID = process.env.OIDC_CLIENT_ID || "";
|
||||||
export const OIDC_CLIENT_SECRET = process.env.OIDC_CLIENT_SECRET || "";
|
export const OIDC_CLIENT_SECRET = process.env.OIDC_CLIENT_SECRET || "";
|
||||||
export const OIDC_CLIENT_ISSUER = process.env.OIDC_CLIENT_ISSUER || "";
|
export const OIDC_CLIENT_ISSUER = process.env.OIDC_CLIENT_ISSUER || "";
|
||||||
export const DEBUG_IGNORE_SSL = process.env.DEBUG_IGNORE_SSL ? process.env.DEBUG_IGNORE_SSL == "true" : false;
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
SECRET_KEY,
|
SECRET_KEY,
|
||||||
|
@ -16,6 +16,7 @@ export const isMapDetailsData = new tg.IsInterface()
|
|||||||
tags: tg.isArray(tg.isString),
|
tags: tg.isArray(tg.isString),
|
||||||
textures: tg.isArray(isCharacterTexture),
|
textures: tg.isArray(isCharacterTexture),
|
||||||
contactPage: tg.isUnion(tg.isString, tg.isUndefined),
|
contactPage: tg.isUnion(tg.isString, tg.isUndefined),
|
||||||
|
authenticationMandatory: tg.isUnion(tg.isBoolean, tg.isUndefined),
|
||||||
})
|
})
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user