Add endpoints on pusher to resolve wokas
This commit is contained in:
committed by
David Négrier
parent
f993aa4f5a
commit
2161a40e05
@@ -6,6 +6,7 @@ import { PrometheusController } from "./Controller/PrometheusController";
|
||||
import { DebugController } from "./Controller/DebugController";
|
||||
import { AdminController } from "./Controller/AdminController";
|
||||
import { OpenIdProfileController } from "./Controller/OpenIdProfileController";
|
||||
import { WokaListController } from "./Controller/WokaListController";
|
||||
import HyperExpress from "hyper-express";
|
||||
import { cors } from "./Middleware/Cors";
|
||||
|
||||
@@ -29,6 +30,7 @@ class App {
|
||||
new DebugController(webserver);
|
||||
new AdminController(webserver);
|
||||
new OpenIdProfileController(webserver);
|
||||
new WokaListController(webserver);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ export class AuthenticateController extends BaseHttpController {
|
||||
//if not nonce and code, user connected in anonymous
|
||||
//get data with identifier and return token
|
||||
if (!code && !nonce) {
|
||||
return res.json(JSON.stringify({ ...resUserData, authToken: token }));
|
||||
return res.json({ ...resUserData, authToken: token });
|
||||
}
|
||||
console.error("Token cannot to be check on OpenId provider");
|
||||
res.status(500);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { hasToken } from "../Middleware/HasToken";
|
||||
import { BaseHttpController } from "./BaseHttpController";
|
||||
import { ADMIN_API_URL } from "../Enum/EnvironmentVariable";
|
||||
import { adminWokaService } from "..//Services/AdminWokaService";
|
||||
import { localWokaService } from "..//Services/LocalWokaService";
|
||||
import { WokaServiceInterface } from "src/Services/WokaServiceInterface";
|
||||
import { Server } from "hyper-express";
|
||||
|
||||
export class WokaListController extends BaseHttpController {
|
||||
private wokaService: WokaServiceInterface;
|
||||
|
||||
constructor(app: Server) {
|
||||
super(app);
|
||||
this.wokaService = ADMIN_API_URL ? adminWokaService : localWokaService;
|
||||
}
|
||||
|
||||
routes() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
this.app.get("/woka-list", { middlewares: [hasToken] }, async (req, res) => {
|
||||
const token = req.header("Authorization");
|
||||
const wokaList = await this.wokaService.getWokaList(token);
|
||||
|
||||
if (!wokaList) {
|
||||
return res.status(500).send("Error on getting woka list");
|
||||
}
|
||||
|
||||
return res.status(200).json(wokaList);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
this.app.post("/woka-details", async (req, res) => {
|
||||
const body = await req.json();
|
||||
if (!body || !body.textureIds) {
|
||||
return res.status(400);
|
||||
}
|
||||
|
||||
const textureIds = body.textureIds;
|
||||
const wokaDetails = await this.wokaService.fetchWokaDetails(textureIds);
|
||||
|
||||
if (!wokaDetails) {
|
||||
return res.json({ details: [] });
|
||||
}
|
||||
|
||||
return res.json(wokaDetails);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import * as tg from "generic-type-guard";
|
||||
|
||||
//The list of all the player textures, both the default models and the partial textures used for customization
|
||||
|
||||
export const isWokaTexture = new tg.IsInterface()
|
||||
.withProperties({
|
||||
id: tg.isString,
|
||||
name: tg.isString,
|
||||
url: tg.isString,
|
||||
position: tg.isNumber,
|
||||
})
|
||||
.withOptionalProperties({
|
||||
tags: tg.isArray(tg.isString),
|
||||
tintable: tg.isBoolean,
|
||||
})
|
||||
.get();
|
||||
|
||||
export type WokaTexture = tg.GuardedType<typeof isWokaTexture>;
|
||||
|
||||
export const isWokaTextureCollection = new tg.IsInterface()
|
||||
.withProperties({
|
||||
name: tg.isString,
|
||||
position: tg.isNumber,
|
||||
textures: tg.isArray(isWokaTexture),
|
||||
})
|
||||
.get();
|
||||
|
||||
export type WokaTextureCollection = tg.GuardedType<typeof isWokaTextureCollection>;
|
||||
|
||||
export const isWokaPartType = new tg.IsInterface()
|
||||
.withProperties({
|
||||
collections: tg.isArray(isWokaTextureCollection),
|
||||
})
|
||||
.withOptionalProperties({
|
||||
required: tg.isBoolean,
|
||||
})
|
||||
.get();
|
||||
|
||||
export type WokaPartType = tg.GuardedType<typeof isWokaPartType>;
|
||||
|
||||
export const isWokaList = new tg.IsInterface().withStringIndexSignature(isWokaPartType).get();
|
||||
|
||||
export type WokaList = tg.GuardedType<typeof isWokaList>;
|
||||
|
||||
export const wokaPartNames = ["woka", "body", "eyes", "hair", "clothes", "hat", "accessory"];
|
||||
|
||||
export const isWokaDetail = new tg.IsInterface()
|
||||
.withProperties({
|
||||
id: tg.isString,
|
||||
})
|
||||
.withOptionalProperties({
|
||||
texture: tg.isString,
|
||||
})
|
||||
.get();
|
||||
|
||||
export type WokaDetail = tg.GuardedType<typeof isWokaDetail>;
|
||||
|
||||
export const isWokaDetailsResult = new tg.IsInterface()
|
||||
.withProperties({
|
||||
details: tg.isArray(isWokaDetail),
|
||||
})
|
||||
.get();
|
||||
|
||||
export type WokaDetailsResult = tg.GuardedType<typeof isWokaDetailsResult>;
|
||||
@@ -0,0 +1,16 @@
|
||||
import Request from "hyper-express/types/components/http/Request";
|
||||
import Response from "hyper-express/types/components/http/Response";
|
||||
import { MiddlewareNext, MiddlewarePromise } from "hyper-express/types/components/router/Router";
|
||||
|
||||
export function hasToken(req: Request, res: Response, next?: MiddlewareNext): MiddlewarePromise {
|
||||
const authorizationHeader = req.header("Authorization");
|
||||
|
||||
if (!authorizationHeader) {
|
||||
res.status(401).send("Undefined authorization header");
|
||||
return;
|
||||
}
|
||||
|
||||
if (next) {
|
||||
next();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import axios from "axios";
|
||||
import { ADMIN_API_TOKEN, ADMIN_API_URL } from "../Enum/EnvironmentVariable";
|
||||
import { isWokaDetailsResult, isWokaList, WokaDetailsResult, WokaList } from "../Enum/PlayerTextures";
|
||||
import { WokaServiceInterface } from "./WokaServiceInterface";
|
||||
|
||||
class AdminWokaService implements WokaServiceInterface {
|
||||
/**
|
||||
* Returns the list of all available Wokas for the current user.
|
||||
*/
|
||||
getWokaList(token: string): Promise<WokaList | undefined> {
|
||||
return axios
|
||||
.get(`${ADMIN_API_URL}/api/woka-list/${token}`, {
|
||||
headers: { Authorization: `${ADMIN_API_TOKEN}` },
|
||||
})
|
||||
.then((res) => {
|
||||
if (isWokaList(res.data)) {
|
||||
throw new Error("Bad response format provided by woka list endpoint");
|
||||
}
|
||||
return res.data;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`Cannot get woka list from admin API with token: ${token}`, err);
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL of all the images for the given texture ids.
|
||||
*
|
||||
* Key: texture id
|
||||
* Value: URL
|
||||
*
|
||||
* If one of the textures cannot be found, undefined is returned
|
||||
*/
|
||||
fetchWokaDetails(textureIds: string[]): Promise<WokaDetailsResult | undefined> {
|
||||
return axios
|
||||
.post(
|
||||
`${ADMIN_API_URL}/api/woka-details`,
|
||||
{
|
||||
textureIds,
|
||||
},
|
||||
{
|
||||
headers: { Authorization: `${ADMIN_API_TOKEN}` },
|
||||
}
|
||||
)
|
||||
.then((res) => {
|
||||
if (isWokaDetailsResult(res.data)) {
|
||||
throw new Error("Bad response format provided by woka detail endpoint");
|
||||
}
|
||||
|
||||
const result: WokaDetailsResult = res.data;
|
||||
if (result.details.length !== textureIds.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
for (const detail of result.details) {
|
||||
if (!detail.texture) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
return res.data;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`Cannot get woka details from admin API with ids: ${textureIds}`, err);
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const adminWokaService = new AdminWokaService();
|
||||
@@ -0,0 +1,64 @@
|
||||
import { WokaDetail, WokaDetailsResult, WokaList, wokaPartNames } from "../Enum/PlayerTextures";
|
||||
import { WokaServiceInterface } from "./WokaServiceInterface";
|
||||
|
||||
class LocalWokaService implements WokaServiceInterface {
|
||||
/**
|
||||
* Returns the list of all available Wokas & Woka Parts for the current user.
|
||||
*/
|
||||
async getWokaList(token: string): Promise<WokaList | undefined> {
|
||||
const wokaData: WokaList = await require("../../data/woka.json");
|
||||
if (!wokaData) {
|
||||
return undefined;
|
||||
}
|
||||
return wokaData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL of all the images for the given texture ids.
|
||||
*
|
||||
* Key: texture id
|
||||
* Value: URL
|
||||
*
|
||||
* If one of the textures cannot be found, undefined is returned (and the user should be redirected to Woka choice page!)
|
||||
*/
|
||||
async fetchWokaDetails(textureIds: string[]): Promise<WokaDetailsResult | undefined> {
|
||||
const wokaData: WokaList = await require("../../data/woka.json");
|
||||
const textures = new Map<string, string>();
|
||||
const searchIds = new Set(textureIds);
|
||||
|
||||
for (const part of wokaPartNames) {
|
||||
const wokaPartType = wokaData[part];
|
||||
if (!wokaPartType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const collection of wokaPartType.collections) {
|
||||
for (const id of searchIds) {
|
||||
const texture = collection.textures.find((texture) => texture.id === id);
|
||||
|
||||
if (texture) {
|
||||
textures.set(id, texture.url);
|
||||
searchIds.delete(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (textureIds.length !== textures.size) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const details: WokaDetail[] = [];
|
||||
|
||||
textures.forEach((value, key) => {
|
||||
details.push({
|
||||
id: key,
|
||||
texture: value,
|
||||
});
|
||||
});
|
||||
|
||||
return { details };
|
||||
}
|
||||
}
|
||||
|
||||
export const localWokaService = new LocalWokaService();
|
||||
@@ -0,0 +1,18 @@
|
||||
import { WokaDetailsResult, WokaList } from "../Enum/PlayerTextures";
|
||||
|
||||
export interface WokaServiceInterface {
|
||||
/**
|
||||
* Returns the list of all available Wokas for the current user.
|
||||
*/
|
||||
getWokaList(token: string): Promise<WokaList | undefined>;
|
||||
|
||||
/**
|
||||
* Returns the URL of all the images for the given texture ids.
|
||||
*
|
||||
* Key: texture id
|
||||
* Value: URL
|
||||
*
|
||||
* If one of the textures cannot be found, undefined is returned (and the user should be redirected to Woka choice page!)
|
||||
*/
|
||||
fetchWokaDetails(textureIds: string[]): Promise<WokaDetailsResult | undefined>;
|
||||
}
|
||||
Reference in New Issue
Block a user