Admin /api/map endpoint return type is now generated with generic type guards
This commit is contained in:
parent
d0d191fc28
commit
a4a123c331
@ -22,13 +22,14 @@ import { UserMovesMessage } from "../Messages/generated/messages_pb";
|
|||||||
import { TemplatedApp } from "uWebSockets.js";
|
import { TemplatedApp } from "uWebSockets.js";
|
||||||
import { parse } from "query-string";
|
import { parse } from "query-string";
|
||||||
import { jwtTokenManager } from "../Services/JWTTokenManager";
|
import { jwtTokenManager } from "../Services/JWTTokenManager";
|
||||||
import { adminApi, CharacterTexture, 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 } 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";
|
||||||
|
import { CharacterTexture } from "../Services/AdminApi/CharacterTexture";
|
||||||
|
|
||||||
export class IoSocketController {
|
export class IoSocketController {
|
||||||
private nextUserId: number = 1;
|
private nextUserId: number = 1;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { HttpRequest, HttpResponse, TemplatedApp } from "uWebSockets.js";
|
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, MapDetailsData } from "../Services/AdminApi";
|
import { adminApi } from "../Services/AdminApi";
|
||||||
import { ADMIN_API_URL } from "../Enum/EnvironmentVariable";
|
import { ADMIN_API_URL } from "../Enum/EnvironmentVariable";
|
||||||
import { GameRoomPolicyTypes } from "../Model/PusherRoom";
|
import { GameRoomPolicyTypes } from "../Model/PusherRoom";
|
||||||
|
import { MapDetailsData } from "../Services/AdminApi/MapDetailsData";
|
||||||
|
|
||||||
export class MapController extends BaseController {
|
export class MapController extends BaseController {
|
||||||
constructor(private App: TemplatedApp) {
|
constructor(private App: TemplatedApp) {
|
||||||
@ -57,6 +58,7 @@ export class MapController extends BaseController {
|
|||||||
policy_type: GameRoomPolicyTypes.ANONYMOUS_POLICY,
|
policy_type: GameRoomPolicyTypes.ANONYMOUS_POLICY,
|
||||||
roomSlug: "", // Deprecated
|
roomSlug: "", // Deprecated
|
||||||
tags: [],
|
tags: [],
|
||||||
|
textures: [],
|
||||||
} as MapDetailsData)
|
} as MapDetailsData)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import {
|
|||||||
SubMessage,
|
SubMessage,
|
||||||
} from "../../Messages/generated/messages_pb";
|
} from "../../Messages/generated/messages_pb";
|
||||||
import { WebSocket } from "uWebSockets.js";
|
import { WebSocket } from "uWebSockets.js";
|
||||||
import { CharacterTexture } from "../../Services/AdminApi";
|
|
||||||
import { ClientDuplexStream } from "grpc";
|
import { ClientDuplexStream } from "grpc";
|
||||||
import { Zone } from "_Model/Zone";
|
import { Zone } from "_Model/Zone";
|
||||||
|
|
||||||
|
@ -9,9 +9,9 @@ import {
|
|||||||
SubMessage,
|
SubMessage,
|
||||||
} from "../../Messages/generated/messages_pb";
|
} from "../../Messages/generated/messages_pb";
|
||||||
import { WebSocket } from "uWebSockets.js";
|
import { WebSocket } from "uWebSockets.js";
|
||||||
import { CharacterTexture } from "../../Services/AdminApi";
|
|
||||||
import { ClientDuplexStream } from "grpc";
|
import { ClientDuplexStream } from "grpc";
|
||||||
import { Zone } from "_Model/Zone";
|
import { Zone } from "_Model/Zone";
|
||||||
|
import { CharacterTexture } from "../../Services/AdminApi/CharacterTexture";
|
||||||
|
|
||||||
export type BackConnection = ClientDuplexStream<PusherToBackMessage, ServerToClientMessage>;
|
export type BackConnection = ClientDuplexStream<PusherToBackMessage, ServerToClientMessage>;
|
||||||
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { ADMIN_API_TOKEN, ADMIN_API_URL } from "../Enum/EnvironmentVariable";
|
import { ADMIN_API_TOKEN, ADMIN_API_URL } from "../Enum/EnvironmentVariable";
|
||||||
import Axios from "axios";
|
import Axios from "axios";
|
||||||
import { GameRoomPolicyTypes } from "_Model/PusherRoom";
|
import { GameRoomPolicyTypes } from "_Model/PusherRoom";
|
||||||
|
import { CharacterTexture } from "./AdminApi/CharacterTexture";
|
||||||
|
import { MapDetailsData } from "./AdminApi/MapDetailsData";
|
||||||
|
import { RoomRedirect } from "./AdminApi/RoomRedirect";
|
||||||
|
|
||||||
export interface AdminApiData {
|
export interface AdminApiData {
|
||||||
roomUrl: string;
|
roomUrl: string;
|
||||||
@ -12,25 +15,11 @@ export interface AdminApiData {
|
|||||||
textures: CharacterTexture[];
|
textures: CharacterTexture[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MapDetailsData {
|
|
||||||
roomSlug: string;
|
|
||||||
mapUrl: string;
|
|
||||||
policy_type: GameRoomPolicyTypes;
|
|
||||||
tags: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AdminBannedData {
|
export interface AdminBannedData {
|
||||||
is_banned: boolean;
|
is_banned: boolean;
|
||||||
message: string;
|
message: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CharacterTexture {
|
|
||||||
id: number;
|
|
||||||
level: number;
|
|
||||||
url: string;
|
|
||||||
rights: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FetchMemberDataByUuidResponse {
|
export interface FetchMemberDataByUuidResponse {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
@ -41,7 +30,7 @@ export interface FetchMemberDataByUuidResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AdminApi {
|
class AdminApi {
|
||||||
async fetchMapDetails(playUri: string): Promise<MapDetailsData> {
|
async fetchMapDetails(playUri: string): Promise<MapDetailsData | RoomRedirect> {
|
||||||
if (!ADMIN_API_URL) {
|
if (!ADMIN_API_URL) {
|
||||||
return Promise.reject(new Error("No admin backoffice set!"));
|
return Promise.reject(new Error("No admin backoffice set!"));
|
||||||
}
|
}
|
||||||
|
11
pusher/src/Services/AdminApi/CharacterTexture.ts
Normal file
11
pusher/src/Services/AdminApi/CharacterTexture.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import * as tg from "generic-type-guard";
|
||||||
|
|
||||||
|
export const isCharacterTexture = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
id: tg.isNumber,
|
||||||
|
level: tg.isNumber,
|
||||||
|
url: tg.isString,
|
||||||
|
rights: tg.isString,
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
export type CharacterTexture = tg.GuardedType<typeof isCharacterTexture>;
|
20
pusher/src/Services/AdminApi/MapDetailsData.ts
Normal file
20
pusher/src/Services/AdminApi/MapDetailsData.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import * as tg from "generic-type-guard";
|
||||||
|
import { GameRoomPolicyTypes } from "_Model/PusherRoom";
|
||||||
|
import { isCharacterTexture } from "./CharacterTexture";
|
||||||
|
import { isAny, isNumber } from "generic-type-guard";
|
||||||
|
|
||||||
|
/*const isNumericEnum =
|
||||||
|
<T extends { [n: number]: string }>(vs: T) =>
|
||||||
|
(v: any): v is T =>
|
||||||
|
typeof v === "number" && v in vs;*/
|
||||||
|
|
||||||
|
export const isMapDetailsData = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
roomSlug: tg.isOptional(tg.isString), // deprecated
|
||||||
|
mapUrl: tg.isString,
|
||||||
|
policy_type: isNumber, //isNumericEnum(GameRoomPolicyTypes),
|
||||||
|
tags: tg.isArray(tg.isString),
|
||||||
|
textures: tg.isArray(isCharacterTexture),
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
export type MapDetailsData = tg.GuardedType<typeof isMapDetailsData>;
|
8
pusher/src/Services/AdminApi/RoomRedirect.ts
Normal file
8
pusher/src/Services/AdminApi/RoomRedirect.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import * as tg from "generic-type-guard";
|
||||||
|
|
||||||
|
export const isRoomRedirect = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
redirectUrl: tg.isString,
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
export type RoomRedirect = tg.GuardedType<typeof isRoomRedirect>;
|
@ -33,7 +33,7 @@ import {
|
|||||||
} 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, SECRET_JITSI_KEY } from "../Enum/EnvironmentVariable";
|
import { ADMIN_API_URL, JITSI_ISS, SECRET_JITSI_KEY } from "../Enum/EnvironmentVariable";
|
||||||
import { adminApi, CharacterTexture } from "./AdminApi";
|
import { adminApi } from "./AdminApi";
|
||||||
import { emitInBatch } from "./IoSocketHelpers";
|
import { emitInBatch } from "./IoSocketHelpers";
|
||||||
import Jwt from "jsonwebtoken";
|
import Jwt from "jsonwebtoken";
|
||||||
import { JITSI_URL } from "../Enum/EnvironmentVariable";
|
import { JITSI_URL } from "../Enum/EnvironmentVariable";
|
||||||
@ -44,6 +44,8 @@ import { GroupDescriptor, UserDescriptor, ZoneEventListener } from "_Model/Zone"
|
|||||||
import Debug from "debug";
|
import Debug from "debug";
|
||||||
import { ExAdminSocketInterface } from "_Model/Websocket/ExAdminSocketInterface";
|
import { ExAdminSocketInterface } from "_Model/Websocket/ExAdminSocketInterface";
|
||||||
import { WebSocket } from "uWebSockets.js";
|
import { WebSocket } from "uWebSockets.js";
|
||||||
|
import { isRoomRedirect } from "./AdminApi/RoomRedirect";
|
||||||
|
import { CharacterTexture } from "./AdminApi/CharacterTexture";
|
||||||
|
|
||||||
const debug = Debug("socket");
|
const debug = Debug("socket");
|
||||||
|
|
||||||
@ -374,9 +376,15 @@ export class SocketManager implements ZoneEventListener {
|
|||||||
|
|
||||||
public async updateRoomWithAdminData(room: PusherRoom): Promise<void> {
|
public async updateRoomWithAdminData(room: PusherRoom): Promise<void> {
|
||||||
const data = await adminApi.fetchMapDetails(room.roomUrl);
|
const data = await adminApi.fetchMapDetails(room.roomUrl);
|
||||||
|
|
||||||
|
if (isRoomRedirect(data)) {
|
||||||
|
// TODO: if the updated room data is actually a redirect, we need to take everybody on the map
|
||||||
|
// and redirect everybody to the new location (so we need to close the connection for everybody)
|
||||||
|
} else {
|
||||||
room.tags = data.tags;
|
room.tags = data.tags;
|
||||||
room.policyType = Number(data.policy_type);
|
room.policyType = Number(data.policy_type);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
emitPlayGlobalMessage(client: ExSocketInterface, playglobalmessage: PlayGlobalMessage) {
|
emitPlayGlobalMessage(client: ExSocketInterface, playglobalmessage: PlayGlobalMessage) {
|
||||||
if (!client.tags.includes("admin")) {
|
if (!client.tags.includes("admin")) {
|
||||||
|
Loading…
Reference in New Issue
Block a user