Merge branch 'localAdmin' into codeAPI
This commit is contained in:
commit
5a416d265e
@ -9,7 +9,7 @@ class AnalyticsClient {
|
||||
constructor() {
|
||||
if (POSTHOG_API_KEY && POSTHOG_URL) {
|
||||
this.posthogPromise = import("posthog-js").then(({ default: posthog }) => {
|
||||
posthog.init(POSTHOG_API_KEY, { api_host: POSTHOG_URL, disable_cookie: true });
|
||||
posthog.init(POSTHOG_API_KEY, { api_host: POSTHOG_URL });
|
||||
//the posthog toolbar need a reference in window to be able to work
|
||||
window.posthog = posthog;
|
||||
return posthog;
|
||||
|
@ -1,7 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { gameManager } from "../../Phaser/Game/GameManager";
|
||||
import { SelectCompanionScene, SelectCompanionSceneName } from "../../Phaser/Login/SelectCompanionScene";
|
||||
import { menuIconVisiblilityStore, menuVisiblilityStore, userIsConnected } from "../../Stores/MenuStore";
|
||||
import {
|
||||
menuIconVisiblilityStore,
|
||||
menuVisiblilityStore,
|
||||
userIsConnected,
|
||||
profileAvailable,
|
||||
getProfileUrl,
|
||||
} from "../../Stores/MenuStore";
|
||||
import { selectCompanionSceneVisibleStore } from "../../Stores/SelectCompanionStore";
|
||||
import { LoginScene, LoginSceneName } from "../../Phaser/Login/LoginScene";
|
||||
import { loginSceneVisibleStore } from "../../Stores/LoginSceneStore";
|
||||
@ -9,7 +15,6 @@
|
||||
import { SelectCharacterScene, SelectCharacterSceneName } from "../../Phaser/Login/SelectCharacterScene";
|
||||
import { connectionManager } from "../../Connexion/ConnectionManager";
|
||||
import { PROFILE_URL } from "../../Enum/EnvironmentVariable";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
import { EnableCameraScene, EnableCameraSceneName } from "../../Phaser/Login/EnableCameraScene";
|
||||
import { enableCameraSceneVisibilityStore } from "../../Stores/MediaStore";
|
||||
import btnProfileSubMenuCamera from "../images/btn-menu-profile-camera.svg";
|
||||
@ -47,10 +52,6 @@
|
||||
return connectionManager.logout();
|
||||
}
|
||||
|
||||
function getProfileUrl() {
|
||||
return PROFILE_URL + `?token=${localUserStore.getAuthToken()}`;
|
||||
}
|
||||
|
||||
function openEnableCameraScene() {
|
||||
disableMenuStores();
|
||||
enableCameraSceneVisibilityStore.showEnableCameraScene();
|
||||
@ -81,7 +82,7 @@
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
{#if $userIsConnected}
|
||||
{#if $userIsConnected && $profileAvailable}
|
||||
<section>
|
||||
{#if PROFILE_URL != undefined}
|
||||
<iframe title="profile" src={getProfileUrl()} />
|
||||
|
@ -290,12 +290,12 @@ class ConnectionManager {
|
||||
);
|
||||
|
||||
connection.onConnectError((error: object) => {
|
||||
console.log("An error occurred while connecting to socket server. Retrying");
|
||||
console.log("onConnectError => An error occurred while connecting to socket server. Retrying");
|
||||
reject(error);
|
||||
});
|
||||
|
||||
connection.connectionErrorStream.subscribe((event: CloseEvent) => {
|
||||
console.log("An error occurred while connecting to socket server. Retrying");
|
||||
console.log("connectionErrorStream => An error occurred while connecting to socket server. Retrying");
|
||||
reject(
|
||||
new Error(
|
||||
"An error occurred while connecting to socket server. Retrying. Code: " +
|
||||
|
@ -23,6 +23,7 @@ export const DISPLAY_TERMS_OF_USE = getEnvConfig("DISPLAY_TERMS_OF_USE") == "tru
|
||||
export const NODE_ENV = getEnvConfig("NODE_ENV") || "development";
|
||||
export const CONTACT_URL = getEnvConfig("CONTACT_URL") || undefined;
|
||||
export const PROFILE_URL = getEnvConfig("PROFILE_URL") || undefined;
|
||||
export const IDENTITY_URL = getEnvConfig("IDENTITY_URL") || undefined;
|
||||
export const POSTHOG_API_KEY: string = (getEnvConfig("POSTHOG_API_KEY") as string) || "";
|
||||
export const POSTHOG_URL = getEnvConfig("POSTHOG_URL") || undefined;
|
||||
export const DISABLE_ANONYMOUS: boolean = getEnvConfig("DISABLE_ANONYMOUS") === "true";
|
||||
|
@ -1,17 +1,27 @@
|
||||
import { get, writable } from "svelte/store";
|
||||
import Timeout = NodeJS.Timeout;
|
||||
import { userIsAdminStore } from "./GameStore";
|
||||
import { CONTACT_URL } from "../Enum/EnvironmentVariable";
|
||||
import { CONTACT_URL, IDENTITY_URL, PROFILE_URL } from "../Enum/EnvironmentVariable";
|
||||
import { analyticsClient } from "../Administration/AnalyticsClient";
|
||||
import type { Translation } from "../i18n/i18n-types";
|
||||
import axios from "axios";
|
||||
import { localUserStore } from "../Connexion/LocalUserStore";
|
||||
|
||||
export const menuIconVisiblilityStore = writable(false);
|
||||
export const menuVisiblilityStore = writable(false);
|
||||
menuVisiblilityStore.subscribe((value) => {
|
||||
if (value) analyticsClient.openedMenu();
|
||||
});
|
||||
export const menuInputFocusStore = writable(false);
|
||||
export const userIsConnected = writable(false);
|
||||
export const profileAvailable = writable(true);
|
||||
|
||||
menuVisiblilityStore.subscribe((value) => {
|
||||
if (value) analyticsClient.openedMenu();
|
||||
if (userIsConnected && value && IDENTITY_URL != null) {
|
||||
axios.get(getMeUrl()).catch((err) => {
|
||||
console.error("menuVisiblilityStore => err => ", err);
|
||||
profileAvailable.set(false);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let warningContainerTimeout: Timeout | null = null;
|
||||
function createWarningContainerStore() {
|
||||
@ -173,3 +183,11 @@ export function handleMenuUnregisterEvent(menuName: string) {
|
||||
subMenusStore.removeScriptingMenu(menuName);
|
||||
customMenuIframe.delete(menuName);
|
||||
}
|
||||
|
||||
export function getProfileUrl() {
|
||||
return PROFILE_URL + `?token=${localUserStore.getAuthToken()}`;
|
||||
}
|
||||
|
||||
export function getMeUrl() {
|
||||
return IDENTITY_URL + `?token=${localUserStore.getAuthToken()}`;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ export default defineConfig({
|
||||
"ADMIN_URL",
|
||||
"CONTACT_URL",
|
||||
"PROFILE_URL",
|
||||
"IDENTITY_URL",
|
||||
"ICON_URL",
|
||||
"DEBUG_MODE",
|
||||
"STUN_SERVER",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { v4 } from "uuid";
|
||||
import { BaseHttpController } from "./BaseHttpController";
|
||||
import { adminApi } from "../Services/AdminApi";
|
||||
import { FetchMemberDataByUuidResponse } from "../Services/AdminApi";
|
||||
import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager";
|
||||
import { parse } from "query-string";
|
||||
import { openIDClient } from "../Services/OpenIDClient";
|
||||
@ -19,6 +19,7 @@ export class AuthenticateController extends BaseHttpController {
|
||||
this.register();
|
||||
this.anonymLogin();
|
||||
this.profileCallback();
|
||||
this.me();
|
||||
}
|
||||
|
||||
openIDLogin() {
|
||||
@ -180,7 +181,7 @@ export class AuthenticateController extends BaseHttpController {
|
||||
if (!code && !nonce) {
|
||||
return res.json({ ...resUserData, authToken: token });
|
||||
}
|
||||
console.error("Token cannot to be check on OpenId provider");
|
||||
console.error("Token cannot be checked on OpenId provider");
|
||||
res.status(500);
|
||||
res.send("User cannot to be connected on openid provider");
|
||||
return;
|
||||
@ -255,7 +256,7 @@ export class AuthenticateController extends BaseHttpController {
|
||||
try {
|
||||
const authTokenData: AuthTokenData = jwtTokenManager.verifyJWTToken(token as string, false);
|
||||
if (authTokenData.accessToken == undefined) {
|
||||
throw Error("Token cannot to be logout on Hydra");
|
||||
throw Error("Token cannot be logout on Hydra");
|
||||
}
|
||||
await openIDClient.logoutUser(authTokenData.accessToken);
|
||||
} catch (error) {
|
||||
@ -320,7 +321,7 @@ export class AuthenticateController extends BaseHttpController {
|
||||
(async () => {
|
||||
const param = await req.json();
|
||||
|
||||
adminApi.setLocale(req.header("accept-language"));
|
||||
adminService.locale = req.header("accept-language");
|
||||
|
||||
//todo: what to do if the organizationMemberToken is already used?
|
||||
const organizationMemberToken: string | null = param.organizationMemberToken;
|
||||
@ -328,13 +329,15 @@ export class AuthenticateController extends BaseHttpController {
|
||||
|
||||
try {
|
||||
if (typeof organizationMemberToken != "string") throw new Error("No organization token");
|
||||
const data = await adminApi.fetchMemberDataByToken(organizationMemberToken, playUri);
|
||||
const data = await adminService.fetchMemberDataByToken(organizationMemberToken, playUri);
|
||||
const userUuid = data.userUuid;
|
||||
const email = data.email;
|
||||
const roomUrl = data.roomUrl;
|
||||
const mapUrlStart = data.mapUrlStart;
|
||||
|
||||
const authToken = jwtTokenManager.createAuthToken(email || userUuid);
|
||||
|
||||
console.info(data);
|
||||
res.json({
|
||||
authToken,
|
||||
userUuid,
|
||||
@ -414,13 +417,13 @@ export class AuthenticateController extends BaseHttpController {
|
||||
try {
|
||||
const authTokenData: AuthTokenData = jwtTokenManager.verifyJWTToken(token as string, false);
|
||||
if (authTokenData.accessToken == undefined) {
|
||||
throw Error("Token cannot to be check on Hydra");
|
||||
throw Error("Token cannot be checked on OpenID connect provider");
|
||||
}
|
||||
await openIDClient.checkTokenAuth(authTokenData.accessToken);
|
||||
|
||||
//get login profile
|
||||
res.status(302);
|
||||
res.setHeader("Location", adminApi.getProfileUrl(authTokenData.accessToken));
|
||||
res.setHeader("Location", adminService.getProfileUrl(authTokenData.accessToken));
|
||||
res.send("");
|
||||
return;
|
||||
} catch (error) {
|
||||
@ -434,4 +437,81 @@ export class AuthenticateController extends BaseHttpController {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /me:
|
||||
* get:
|
||||
* description: ???
|
||||
* parameters:
|
||||
* - name: "token"
|
||||
* in: "query"
|
||||
* description: "A JWT authentication token ???"
|
||||
* required: true
|
||||
* type: "string"
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Data of user connected
|
||||
*/
|
||||
me() {
|
||||
// @ts-ignore
|
||||
this.app.get("/me", async (req, res): void => {
|
||||
const { token } = parse(req.path_query);
|
||||
try {
|
||||
//verify connected by token
|
||||
if (token != undefined) {
|
||||
try {
|
||||
const authTokenData: AuthTokenData = jwtTokenManager.verifyJWTToken(token as string, false);
|
||||
if (authTokenData.accessToken == undefined) {
|
||||
throw Error("Token cannot to be checked on Hydra");
|
||||
}
|
||||
const me = await openIDClient.checkTokenAuth(authTokenData.accessToken);
|
||||
|
||||
//get login profile
|
||||
res.status(200);
|
||||
res.json({ ...me });
|
||||
return;
|
||||
} catch (error) {
|
||||
this.castErrorToResponse(error, res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("me => ERROR", error);
|
||||
this.castErrorToResponse(error, res);
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param email
|
||||
* @param playUri
|
||||
* @param IPAddress
|
||||
* @return
|
||||
|object
|
||||
* @private
|
||||
*/
|
||||
private async getUserByUserIdentifier(
|
||||
email: string,
|
||||
playUri: string,
|
||||
IPAddress: string
|
||||
): Promise<FetchMemberDataByUuidResponse | object> {
|
||||
let data: FetchMemberDataByUuidResponse = {
|
||||
email: email,
|
||||
userUuid: email,
|
||||
tags: [],
|
||||
messages: [],
|
||||
visitCardUrl: null,
|
||||
textures: [],
|
||||
userRoomToken: undefined,
|
||||
};
|
||||
try {
|
||||
data = await adminService.fetchMemberDataByUuid(email, playUri, IPAddress, []);
|
||||
} catch (err) {
|
||||
console.error("openIDCallback => fetchMemberDataByUuid", err);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import {
|
||||
import { UserMovesMessage } from "../Messages/generated/messages_pb";
|
||||
import { parse } from "query-string";
|
||||
import { AdminSocketTokenData, jwtTokenManager, tokenInvalidException } from "../Services/JWTTokenManager";
|
||||
import { adminApi, FetchMemberDataByUuidResponse } from "../Services/AdminApi";
|
||||
import { FetchMemberDataByUuidResponse } from "../Services/AdminApi";
|
||||
import { socketManager } from "../Services/SocketManager";
|
||||
import { emitInBatch } from "../Services/IoSocketHelpers";
|
||||
import { ADMIN_API_URL, ADMIN_SOCKETS_TOKEN, DISABLE_ANONYMOUS, SOCKET_IDLE_TIMER } from "../Enum/EnvironmentVariable";
|
||||
@ -40,6 +40,7 @@ import { localWokaService } from "../Services/LocalWokaService";
|
||||
import { WebSocket } from "uWebSockets.js";
|
||||
import { WokaDetail } from "../Messages/JsonMessages/PlayerTextures";
|
||||
import { z } from "zod";
|
||||
import { adminService } from "../Services/AdminService";
|
||||
import { ErrorApiData, isErrorApiData } from "../Messages/JsonMessages/ErrorApiData";
|
||||
|
||||
/**
|
||||
@ -245,7 +246,7 @@ export class IoSocketController {
|
||||
const websocketExtensions = req.getHeader("sec-websocket-extensions");
|
||||
const IPAddress = req.getHeader("x-forwarded-for");
|
||||
|
||||
adminApi.setLocale(req.getHeader("accept-language"));
|
||||
adminService.locale = req.getHeader("accept-language");
|
||||
|
||||
const roomId = query.roomId;
|
||||
try {
|
||||
@ -314,7 +315,7 @@ export class IoSocketController {
|
||||
if (ADMIN_API_URL) {
|
||||
try {
|
||||
try {
|
||||
userData = await adminApi.fetchMemberDataByUuid(
|
||||
userData = await adminService.fetchMemberDataByUuid(
|
||||
userIdentifier,
|
||||
roomId,
|
||||
IPAddress,
|
||||
|
@ -1,11 +1,8 @@
|
||||
import { adminApi } from "../Services/AdminApi";
|
||||
import { ADMIN_API_URL, DISABLE_ANONYMOUS } from "../Enum/EnvironmentVariable";
|
||||
import { GameRoomPolicyTypes } from "../Model/PusherRoom";
|
||||
import { isMapDetailsData, MapDetailsData } from "../Messages/JsonMessages/MapDetailsData";
|
||||
import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager";
|
||||
import { InvalidTokenError } from "./InvalidTokenError";
|
||||
import { DISABLE_ANONYMOUS } from "../Enum/EnvironmentVariable";
|
||||
import { isMapDetailsData } from "../Messages/JsonMessages/MapDetailsData";
|
||||
import { parse } from "query-string";
|
||||
import { BaseHttpController } from "./BaseHttpController";
|
||||
import { adminService } from "../Services/AdminService";
|
||||
|
||||
export class MapController extends BaseHttpController {
|
||||
// Returns a map mapping map name to file name of the map
|
||||
@ -107,68 +104,15 @@ export class MapController extends BaseHttpController {
|
||||
return;
|
||||
}
|
||||
|
||||
adminApi.setLocale(req.header("accept-language"));
|
||||
|
||||
// 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.status(404);
|
||||
res.json({});
|
||||
return;
|
||||
}
|
||||
|
||||
const mapUrl = roomUrl.protocol + "//" + match[1];
|
||||
|
||||
res.json({
|
||||
mapUrl,
|
||||
policy_type: GameRoomPolicyTypes.ANONYMOUS_POLICY,
|
||||
roomSlug: null, // Deprecated
|
||||
group: null,
|
||||
tags: [],
|
||||
contactPage: null,
|
||||
authenticationMandatory: DISABLE_ANONYMOUS,
|
||||
} as MapDetailsData);
|
||||
|
||||
return;
|
||||
}
|
||||
adminService.locale = req.header("accept-language");
|
||||
|
||||
(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) {
|
||||
try {
|
||||
// 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);
|
||||
} catch (e) {
|
||||
if (e instanceof InvalidTokenError) {
|
||||
// The token was not good, redirect user on login page
|
||||
res.status(401);
|
||||
res.send("Token decrypted error");
|
||||
return;
|
||||
} else {
|
||||
this.castErrorToResponse(e, res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const mapDetails = isMapDetailsData.parse(
|
||||
await adminApi.fetchMapDetails(query.playUri as string, userId)
|
||||
await adminService.fetchMapDetails(query.playUri as string, query.authToken as string)
|
||||
);
|
||||
|
||||
if (DISABLE_ANONYMOUS) {
|
||||
mapDetails.authenticationMandatory = true;
|
||||
}
|
||||
if (DISABLE_ANONYMOUS) mapDetails.authenticationMandatory = true;
|
||||
|
||||
res.json(mapDetails);
|
||||
return;
|
||||
|
@ -7,6 +7,8 @@ import { z } from "zod";
|
||||
import { isWokaDetail } from "../Messages/JsonMessages/PlayerTextures";
|
||||
import qs from "qs";
|
||||
import { AdminInterface } from "./AdminInterface";
|
||||
import { AuthTokenData, jwtTokenManager } from "./JWTTokenManager";
|
||||
import { InvalidTokenError } from "../Controller/InvalidTokenError";
|
||||
|
||||
export interface AdminBannedData {
|
||||
is_banned: boolean;
|
||||
@ -27,19 +29,35 @@ export const isFetchMemberDataByUuidResponse = z.object({
|
||||
export type FetchMemberDataByUuidResponse = z.infer<typeof isFetchMemberDataByUuidResponse>;
|
||||
|
||||
class AdminApi implements AdminInterface {
|
||||
private locale: string = "en";
|
||||
setLocale(locale: string) {
|
||||
console.info("PUSHER LOCALE SET TO :", locale);
|
||||
this.locale = locale;
|
||||
}
|
||||
/**
|
||||
* @var playUri: is url of the room
|
||||
* @var userId: can to be undefined or email or uuid
|
||||
* @return MapDetailsData|RoomRedirect
|
||||
*/
|
||||
async fetchMapDetails(playUri: string, userId?: string): Promise<MapDetailsData | RoomRedirect> {
|
||||
if (!ADMIN_API_URL) {
|
||||
return Promise.reject(new Error("No admin backoffice set!"));
|
||||
locale: string = "en";
|
||||
|
||||
async fetchMapDetails(playUri: string, authToken?: string): Promise<MapDetailsData | RoomRedirect> {
|
||||
let userId: string | undefined = undefined;
|
||||
if (authToken != undefined) {
|
||||
let authTokenData: AuthTokenData;
|
||||
try {
|
||||
authTokenData = jwtTokenManager.verifyJWTToken(authToken);
|
||||
userId = authTokenData.identifier;
|
||||
} catch (e) {
|
||||
try {
|
||||
// Decode token, in this case we don't need to create new token.
|
||||
authTokenData = jwtTokenManager.verifyJWTToken(authToken, true);
|
||||
userId = authTokenData.identifier;
|
||||
console.info("JWT expire, but decoded", userId);
|
||||
} catch (e) {
|
||||
if (e instanceof InvalidTokenError) {
|
||||
throw new Error("Token decrypted error");
|
||||
// The token was not good, redirect user on login page
|
||||
//res.status(401);
|
||||
//res.send("Token decrypted error");
|
||||
//return;
|
||||
} else {
|
||||
throw new Error("Error on decryption of token :" + e);
|
||||
//this.castErrorToResponse(e, res);
|
||||
//return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const params: { playUri: string; userId?: string } = {
|
||||
@ -76,9 +94,6 @@ class AdminApi implements AdminInterface {
|
||||
ipAddress: string,
|
||||
characterLayers: string[]
|
||||
): Promise<FetchMemberDataByUuidResponse> {
|
||||
if (!ADMIN_API_URL) {
|
||||
return Promise.reject(new Error("No admin backoffice set!"));
|
||||
}
|
||||
const res = await Axios.get<unknown, AxiosResponse<unknown>>(ADMIN_API_URL + "/api/room/access", {
|
||||
params: {
|
||||
userIdentifier,
|
||||
@ -106,9 +121,6 @@ class AdminApi implements AdminInterface {
|
||||
}
|
||||
|
||||
async fetchMemberDataByToken(organizationMemberToken: string, playUri: string | null): Promise<AdminApiData> {
|
||||
if (!ADMIN_API_URL) {
|
||||
return Promise.reject(new Error("No admin backoffice set!"));
|
||||
}
|
||||
//todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case.
|
||||
const res = await Axios.get(ADMIN_API_URL + "/api/login-url/" + organizationMemberToken, {
|
||||
params: { playUri },
|
||||
@ -132,9 +144,6 @@ class AdminApi implements AdminInterface {
|
||||
reporterUserUuid: string,
|
||||
reportWorldSlug: string
|
||||
) {
|
||||
if (!ADMIN_API_URL) {
|
||||
return Promise.reject(new Error("No admin backoffice set!"));
|
||||
}
|
||||
return Axios.post(
|
||||
`${ADMIN_API_URL}/api/report`,
|
||||
{
|
||||
@ -150,9 +159,6 @@ class AdminApi implements AdminInterface {
|
||||
}
|
||||
|
||||
async verifyBanUser(userUuid: string, ipAddress: string, roomUrl: string): Promise<AdminBannedData> {
|
||||
if (!ADMIN_API_URL) {
|
||||
return Promise.reject(new Error("No admin backoffice set!"));
|
||||
}
|
||||
//todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case.
|
||||
return Axios.get(
|
||||
ADMIN_API_URL +
|
||||
@ -170,10 +176,6 @@ class AdminApi implements AdminInterface {
|
||||
}
|
||||
|
||||
async getUrlRoomsFromSameWorld(roomUrl: string): Promise<string[]> {
|
||||
if (!ADMIN_API_URL) {
|
||||
return Promise.reject(new Error("No admin backoffice set!"));
|
||||
}
|
||||
|
||||
return Axios.get(ADMIN_API_URL + "/api/room/sameWorld" + "?roomUrl=" + encodeURIComponent(roomUrl), {
|
||||
headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": this.locale },
|
||||
}).then((data) => {
|
||||
@ -181,10 +183,6 @@ class AdminApi implements AdminInterface {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param accessToken
|
||||
*/
|
||||
getProfileUrl(accessToken: string): string {
|
||||
if (!OPID_PROFILE_SCREEN_PROVIDER) {
|
||||
throw new Error("No admin backoffice set!");
|
||||
@ -192,7 +190,7 @@ class AdminApi implements AdminInterface {
|
||||
return `${OPID_PROFILE_SCREEN_PROVIDER}?accessToken=${accessToken}`;
|
||||
}
|
||||
|
||||
async logoutOauth(token: string) {
|
||||
async logoutOauth(token: string): Promise<void> {
|
||||
await Axios.get(ADMIN_API_URL + `/oauth/logout?token=${token}`);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,74 @@
|
||||
import { FetchMemberDataByUuidResponse } from "./AdminApi";
|
||||
import { AdminBannedData, FetchMemberDataByUuidResponse } from "./AdminApi";
|
||||
import { MapDetailsData } from "../Messages/JsonMessages/MapDetailsData";
|
||||
import { RoomRedirect } from "../Messages/JsonMessages/RoomRedirect";
|
||||
import { AdminApiData } from "../Messages/JsonMessages/AdminApiData";
|
||||
|
||||
export interface AdminInterface {
|
||||
locale: string;
|
||||
|
||||
/**
|
||||
* @var playUri: is url of the room
|
||||
* @var userIdentifier: can to be undefined or email or uuid
|
||||
* @var ipAddress
|
||||
* @var characterLayers
|
||||
* @return MapDetailsData|RoomRedirect
|
||||
*/
|
||||
fetchMemberDataByUuid(
|
||||
userIdentifier: string,
|
||||
playUri: string,
|
||||
ipAddress: string,
|
||||
characterLayers: string[]
|
||||
): Promise<FetchMemberDataByUuidResponse>;
|
||||
|
||||
/**
|
||||
* @var playUri: is url of the room
|
||||
* @var userId: can to be undefined or email or uuid
|
||||
* @return MapDetailsData|RoomRedirect
|
||||
*/
|
||||
fetchMapDetails(playUri: string, authToken?: string): Promise<MapDetailsData | RoomRedirect>;
|
||||
|
||||
/**
|
||||
* @param organizationMemberToken
|
||||
* @param playUri
|
||||
* @return AdminApiData
|
||||
*/
|
||||
fetchMemberDataByToken(organizationMemberToken: string, playUri: string | null): Promise<AdminApiData>;
|
||||
|
||||
/**
|
||||
* @param reportedUserUuid
|
||||
* @param reportedUserComment
|
||||
* @param reporterUserUuid
|
||||
* @param reportWorldSlug
|
||||
*/
|
||||
reportPlayer(
|
||||
reportedUserUuid: string,
|
||||
reportedUserComment: string,
|
||||
reporterUserUuid: string,
|
||||
reportWorldSlug: string
|
||||
): Promise<unknown>;
|
||||
|
||||
/**
|
||||
* @param userUuid
|
||||
* @param ipAddress
|
||||
* @param roomUrl
|
||||
* @return AdminBannedData
|
||||
*/
|
||||
verifyBanUser(userUuid: string, ipAddress: string, roomUrl: string): Promise<AdminBannedData>;
|
||||
|
||||
/**
|
||||
* @param roomUrl
|
||||
* @return string[]
|
||||
*/
|
||||
getUrlRoomsFromSameWorld(roomUrl: string): Promise<string[]>;
|
||||
|
||||
/**
|
||||
* @param accessToken
|
||||
* @return string
|
||||
*/
|
||||
getProfileUrl(accessToken: string): string;
|
||||
|
||||
/**
|
||||
* @param token
|
||||
*/
|
||||
logoutOauth(token: string): Promise<void>;
|
||||
}
|
||||
|
@ -1,10 +1,17 @@
|
||||
import { FetchMemberDataByUuidResponse } from "./AdminApi";
|
||||
import { AdminBannedData, FetchMemberDataByUuidResponse } from "./AdminApi";
|
||||
import { AdminInterface } from "./AdminInterface";
|
||||
import { MapDetailsData } from "../Messages/JsonMessages/MapDetailsData";
|
||||
import { RoomRedirect } from "../Messages/JsonMessages/RoomRedirect";
|
||||
import { GameRoomPolicyTypes } from "../Model/PusherRoom";
|
||||
import { DISABLE_ANONYMOUS } from "../Enum/EnvironmentVariable";
|
||||
import { AdminApiData } from "../Messages/JsonMessages/AdminApiData";
|
||||
|
||||
/**
|
||||
* A local class mocking a real admin if no admin is configured.
|
||||
*/
|
||||
class LocalAdmin implements AdminInterface {
|
||||
locale: string = "en";
|
||||
|
||||
fetchMemberDataByUuid(
|
||||
userIdentifier: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
@ -24,6 +31,89 @@ class LocalAdmin implements AdminInterface {
|
||||
userRoomToken: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
fetchMapDetails(
|
||||
playUri: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
authToken?: string
|
||||
): Promise<MapDetailsData | RoomRedirect> {
|
||||
const roomUrl = new URL(playUri);
|
||||
|
||||
const match = /\/_\/[^/]+\/(.+)/.exec(roomUrl.pathname);
|
||||
if (!match) {
|
||||
throw new Error("URL format is not good");
|
||||
}
|
||||
|
||||
const mapUrl = roomUrl.protocol + "//" + match[1];
|
||||
|
||||
return Promise.resolve({
|
||||
mapUrl,
|
||||
policy_type: GameRoomPolicyTypes.ANONYMOUS_POLICY,
|
||||
tags: [],
|
||||
authenticationMandatory: DISABLE_ANONYMOUS,
|
||||
roomSlug: null,
|
||||
contactPage: null,
|
||||
group: null,
|
||||
iframeAuthentication: null,
|
||||
loadingLogo: null,
|
||||
loginSceneLogo: null,
|
||||
});
|
||||
}
|
||||
|
||||
async fetchMemberDataByToken(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
organizationMemberToken: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
playUri: string | null
|
||||
): Promise<AdminApiData> {
|
||||
return Promise.reject(new Error("No admin backoffice set!"));
|
||||
}
|
||||
|
||||
reportPlayer(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
reportedUserUuid: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
reportedUserComment: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
reporterUserUuid: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
reportWorldSlug: string
|
||||
) {
|
||||
return Promise.reject(new Error("No admin backoffice set!"));
|
||||
}
|
||||
|
||||
async verifyBanUser(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
userUuid: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
ipAddress: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
roomUrl: string
|
||||
): Promise<AdminBannedData> {
|
||||
return Promise.reject(new Error("No admin backoffice set!"));
|
||||
}
|
||||
|
||||
async getUrlRoomsFromSameWorld(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
roomUrl: string
|
||||
): Promise<string[]> {
|
||||
return Promise.reject(new Error("No admin backoffice set!"));
|
||||
}
|
||||
|
||||
getProfileUrl(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
accessToken: string
|
||||
): string {
|
||||
new Error("No admin backoffice set!");
|
||||
return "";
|
||||
}
|
||||
|
||||
async logoutOauth(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
token: string
|
||||
): Promise<void> {
|
||||
return Promise.reject(new Error("No admin backoffice set!"));
|
||||
}
|
||||
}
|
||||
|
||||
export const localAdmin = new LocalAdmin();
|
||||
|
@ -44,7 +44,6 @@ import {
|
||||
} from "../Messages/generated/messages_pb";
|
||||
import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils";
|
||||
import { ADMIN_API_URL, JITSI_ISS, JITSI_URL, SECRET_JITSI_KEY } from "../Enum/EnvironmentVariable";
|
||||
import { adminApi } from "./AdminApi";
|
||||
import { emitInBatch } from "./IoSocketHelpers";
|
||||
import Jwt from "jsonwebtoken";
|
||||
import { clientEventsEmitter } from "./ClientEventsEmitter";
|
||||
@ -55,6 +54,7 @@ import Debug from "debug";
|
||||
import { ExAdminSocketInterface } from "../Model/Websocket/ExAdminSocketInterface";
|
||||
import { compressors } from "hyper-express";
|
||||
import { isMapDetailsData } from "../Messages/JsonMessages/MapDetailsData";
|
||||
import { adminService } from "./AdminService";
|
||||
import { ErrorApiData } from "../Messages/JsonMessages/ErrorApiData";
|
||||
|
||||
const debug = Debug("socket");
|
||||
@ -359,7 +359,7 @@ export class SocketManager implements ZoneEventListener {
|
||||
|
||||
async handleReportMessage(client: ExSocketInterface, reportPlayerMessage: ReportPlayerMessage) {
|
||||
try {
|
||||
await adminApi.reportPlayer(
|
||||
await adminService.reportPlayer(
|
||||
reportPlayerMessage.getReporteduseruuid(),
|
||||
reportPlayerMessage.getReportcomment(),
|
||||
client.userUuid,
|
||||
@ -445,7 +445,7 @@ export class SocketManager implements ZoneEventListener {
|
||||
}
|
||||
|
||||
public async updateRoomWithAdminData(room: PusherRoom): Promise<void> {
|
||||
const data = await adminApi.fetchMapDetails(room.roomUrl);
|
||||
const data = await adminService.fetchMapDetails(room.roomUrl);
|
||||
const mapDetailsData = isMapDetailsData.safeParse(data);
|
||||
|
||||
if (mapDetailsData.success) {
|
||||
@ -696,7 +696,7 @@ export class SocketManager implements ZoneEventListener {
|
||||
let tabUrlRooms: string[];
|
||||
|
||||
if (playGlobalMessageEvent.getBroadcasttoworld()) {
|
||||
tabUrlRooms = await adminApi.getUrlRoomsFromSameWorld(clientRoomUrl);
|
||||
tabUrlRooms = await adminService.getUrlRoomsFromSameWorld(clientRoomUrl);
|
||||
} else {
|
||||
tabUrlRooms = [clientRoomUrl];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user