Merge branch 'develop' of github.com:thecodingmachine/workadventure into uws
# Conflicts: # back/src/Controller/AdminController.ts # back/src/Controller/AuthenticateController.ts # back/src/Controller/IoSocketController.ts # back/src/Controller/MapController.ts # benchmark/index.ts # front/src/Connexion/RoomConnection.ts
This commit is contained in:
commit
9f3577286d
24 changed files with 342 additions and 337 deletions
|
@ -3,7 +3,6 @@ import {IoSocketController} from "./Controller/IoSocketController"; //TODO fix i
|
|||
import {AuthenticateController} from "./Controller/AuthenticateController"; //TODO fix import by "_Controller/..."
|
||||
import {MapController} from "./Controller/MapController";
|
||||
import {PrometheusController} from "./Controller/PrometheusController";
|
||||
import {AdminController} from "./Controller/AdminController";
|
||||
import {DebugController} from "./Controller/DebugController";
|
||||
import {App as uwsApp} from "./Server/sifrr.server";
|
||||
|
||||
|
@ -13,7 +12,6 @@ class App {
|
|||
public authenticateController: AuthenticateController;
|
||||
public mapController: MapController;
|
||||
public prometheusController: PrometheusController;
|
||||
private adminController: AdminController;
|
||||
private debugController: DebugController;
|
||||
|
||||
constructor() {
|
||||
|
@ -39,7 +37,6 @@ class App {
|
|||
this.authenticateController = new AuthenticateController(this.app);
|
||||
this.mapController = new MapController(this.app);
|
||||
this.prometheusController = new PrometheusController(this.app, this.ioSocketController);
|
||||
this.adminController = new AdminController(this.app);
|
||||
this.debugController = new DebugController(this.app, this.ioSocketController);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
import {OK} from "http-status-codes";
|
||||
import {ADMIN_API_TOKEN, ADMIN_API_URL} from "../Enum/EnvironmentVariable";
|
||||
import Axios from "axios";
|
||||
import {HttpRequest, HttpResponse} from "uWebSockets.js";
|
||||
import {parse} from "query-string";
|
||||
import {App} from "../Server/sifrr.server";
|
||||
|
||||
export class AdminController {
|
||||
constructor(private App : App) {
|
||||
this.getLoginUrlByToken();
|
||||
}
|
||||
|
||||
|
||||
getLoginUrlByToken(){
|
||||
this.App.get("/register/:token", (res: HttpResponse, req: HttpRequest) => {
|
||||
(async () => {
|
||||
if (!ADMIN_API_URL) {
|
||||
return res.writeStatus("500 Internal Server Error").end('No admin backoffice set!');
|
||||
}
|
||||
|
||||
const query = parse(req.getQuery());
|
||||
|
||||
const token:string = query.token as string;
|
||||
|
||||
let response = null
|
||||
try {
|
||||
response = await Axios.get(ADMIN_API_URL+'/api/login-url/'+token, { headers: {"Authorization" : `${ADMIN_API_TOKEN}`} })
|
||||
} catch (e) {
|
||||
console.log(e.message)
|
||||
return res.status(e.status || 500).send('An error happened');
|
||||
}
|
||||
|
||||
const organizationSlug = response.data.organizationSlug;
|
||||
const worldSlug = response.data.worldSlug;
|
||||
const roomSlug = response.data.roomSlug;
|
||||
res.writeStatus("200 OK").end(JSON.stringify({organizationSlug, worldSlug, roomSlug}));
|
||||
})();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,11 +1,21 @@
|
|||
import Jwt from "jsonwebtoken";
|
||||
import {SECRET_KEY, URL_ROOM_STARTED} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
|
||||
import {OK} from "http-status-codes";
|
||||
import {ADMIN_API_TOKEN, ADMIN_API_URL, SECRET_KEY, URL_ROOM_STARTED} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
|
||||
import { uuid } from 'uuidv4';
|
||||
import {HttpRequest, HttpResponse, TemplatedApp} from "uWebSockets.js";
|
||||
import {BaseController} from "./BaseController";
|
||||
import Axios from "axios";
|
||||
|
||||
export interface TokenInterface {
|
||||
name: string,
|
||||
userUuid: string
|
||||
}
|
||||
|
||||
interface AdminApiData {
|
||||
organizationSlug: string
|
||||
worldSlug: string
|
||||
roomSlug: string
|
||||
mapUrlStart: string
|
||||
userUuid: string
|
||||
}
|
||||
|
||||
|
@ -16,21 +26,6 @@ export class AuthenticateController extends BaseController {
|
|||
this.login();
|
||||
}
|
||||
|
||||
onAbortedOrFinishedResponse(res: HttpResponse/*, readStream: any*/) {
|
||||
|
||||
console.log("ERROR! onAbortedOrFinishedResponse called!");
|
||||
/*if (res.id == -1) {
|
||||
console.log("ERROR! onAbortedOrFinishedResponse called twice for the same res!");
|
||||
} else {
|
||||
console.log('Stream was closed, openStreams: ' + --openStreams);
|
||||
console.timeEnd(res.id);
|
||||
readStream.destroy();
|
||||
}*/
|
||||
|
||||
/* Mark this response already accounted for */
|
||||
//res.id = -1;
|
||||
}
|
||||
|
||||
//permit to login on application. Return token to connect on Websocket IO.
|
||||
login(){
|
||||
this.App.options("/login", (res: HttpResponse, req: HttpRequest) => {
|
||||
|
@ -47,14 +42,55 @@ export class AuthenticateController extends BaseController {
|
|||
console.warn('Login request was aborted');
|
||||
})
|
||||
const param = await res.json();
|
||||
const userUuid = uuid();
|
||||
const token = Jwt.sign({name: param.name, userUuid: userUuid} as TokenInterface, SECRET_KEY, {expiresIn: '24h'});
|
||||
res.writeStatus("200 OK").end(JSON.stringify({
|
||||
token: token,
|
||||
mapUrlStart: URL_ROOM_STARTED,
|
||||
userId: userUuid,
|
||||
}));
|
||||
|
||||
//todo: what to do if the organizationMemberToken is already used?
|
||||
const organizationMemberToken:string|null = param.organizationMemberToken;
|
||||
|
||||
try {
|
||||
let userUuid;
|
||||
let mapUrlStart;
|
||||
let newUrl = null;
|
||||
|
||||
if (organizationMemberToken) {
|
||||
if (!ADMIN_API_URL) {
|
||||
return res.status(401).send('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 data = await Axios.get(ADMIN_API_URL+'/api/login-url/'+organizationMemberToken,
|
||||
{ headers: {"Authorization" : `${ADMIN_API_TOKEN}`} }
|
||||
).then((res): AdminApiData => res.data);
|
||||
|
||||
userUuid = data.userUuid;
|
||||
mapUrlStart = data.mapUrlStart;
|
||||
newUrl = this.getNewUrlOnAdminAuth(data)
|
||||
} else {
|
||||
userUuid = uuid();
|
||||
mapUrlStart = req.getHeader('host').replace('api.', 'maps.') + URL_ROOM_STARTED;
|
||||
newUrl = null;
|
||||
}
|
||||
|
||||
const authToken = Jwt.sign({userUuid: userUuid}, SECRET_KEY, {expiresIn: '24h'});
|
||||
res.writeStatus("200 OK").end(JSON.stringify({
|
||||
authToken,
|
||||
userUuid,
|
||||
mapUrlStart,
|
||||
newUrl,
|
||||
}));
|
||||
|
||||
} catch (e) {
|
||||
console.log(e.message)
|
||||
res.writeStatus(e.status || "500 Internal Server Error").end('An error happened');
|
||||
}
|
||||
|
||||
|
||||
})();
|
||||
});
|
||||
}
|
||||
|
||||
private getNewUrlOnAdminAuth(data:AdminApiData): string {
|
||||
const organizationSlug = data.organizationSlug;
|
||||
const worldSlug = data.worldSlug;
|
||||
const roomSlug = data.roomSlug;
|
||||
return '/@/'+organizationSlug+'/'+worldSlug+'/'+roomSlug;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,9 +116,6 @@ export class IoSocketController {
|
|||
if (typeof((token as TokenInterface).userUuid) !== 'string') {
|
||||
return false;
|
||||
}
|
||||
if (typeof((token as TokenInterface).name) !== 'string') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -142,45 +139,46 @@ export class IoSocketController {
|
|||
//console.log(socket.handshake.query.token);
|
||||
|
||||
/*if (!socket.handshake.query || !socket.handshake.query.token) {
|
||||
console.error('An authentication error happened, a user tried to connect without a token.');
|
||||
return next(new Error('Authentication error'));
|
||||
}
|
||||
if(socket.handshake.query.token === 'test'){
|
||||
if (ALLOW_ARTILLERY) {
|
||||
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
||||
(socket as ExSocketInterface).userId = this.nextUserId;
|
||||
(socket as ExSocketInterface).userUuid = uuid();
|
||||
this.nextUserId++;
|
||||
(socket as ExSocketInterface).isArtillery = true;
|
||||
console.log((socket as ExSocketInterface).userId);
|
||||
next();
|
||||
return;
|
||||
} else {
|
||||
console.warn("In order to perform a load-testing test on this environment, you must set the ALLOW_ARTILLERY environment variable to 'true'");
|
||||
next();
|
||||
}
|
||||
}
|
||||
(socket as ExSocketInterface).isArtillery = false;
|
||||
if(this.searchClientByToken(socket.handshake.query.token)){
|
||||
console.error('An authentication error happened, a user tried to connect while its token is already connected.');
|
||||
return next(new Error('Authentication error'));
|
||||
}
|
||||
Jwt.verify(socket.handshake.query.token, SECRET_KEY, (err: JsonWebTokenError, tokenDecoded: object) => {
|
||||
if (err) {
|
||||
console.error('An authentication error happened, invalid JsonWebToken.', err);
|
||||
console.error('An authentication error happened, a user tried to connect without a token.');
|
||||
return next(new Error('Authentication error'));
|
||||
}
|
||||
|
||||
if (!this.isValidToken(tokenDecoded)) {
|
||||
return next(new Error('Authentication error, invalid token structure'));
|
||||
if(socket.handshake.query.token === 'test'){
|
||||
if (ALLOW_ARTILLERY) {
|
||||
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
||||
(socket as ExSocketInterface).userId = this.nextUserId;
|
||||
(socket as ExSocketInterface).userUuid = uuid();
|
||||
this.nextUserId++;
|
||||
(socket as ExSocketInterface).isArtillery = true;
|
||||
console.log((socket as ExSocketInterface).userId);
|
||||
next();
|
||||
return;
|
||||
} else {
|
||||
console.warn("In order to perform a load-testing test on this environment, you must set the ALLOW_ARTILLERY environment variable to 'true'");
|
||||
next();
|
||||
}
|
||||
}
|
||||
(socket as ExSocketInterface).isArtillery = false;
|
||||
if(this.searchClientByToken(socket.handshake.query.token)){
|
||||
console.error('An authentication error happened, a user tried to connect while its token is already connected.');
|
||||
return next(new Error('Authentication error'));
|
||||
}
|
||||
Jwt.verify(socket.handshake.query.token, SECRET_KEY, (err: JsonWebTokenError, tokenDecoded: object) => {
|
||||
const tokenInterface = tokenDecoded as TokenInterface;
|
||||
if (err) {
|
||||
console.error('An authentication error happened, invalid JsonWebToken.', err);
|
||||
return next(new Error('Authentication error'));
|
||||
}
|
||||
|
||||
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
||||
(socket as ExSocketInterface).userId = this.nextUserId;
|
||||
(socket as ExSocketInterface).userUuid = tokenDecoded.userUuid;
|
||||
this.nextUserId++;
|
||||
next();
|
||||
});*/
|
||||
if (!this.isValidToken(tokenInterface)) {
|
||||
return next(new Error('Authentication error, invalid token structure'));
|
||||
}
|
||||
|
||||
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
||||
(socket as ExSocketInterface).userId = this.nextUserId;
|
||||
(socket as ExSocketInterface).userUuid = tokenInterface.userUuid;
|
||||
this.nextUserId++;
|
||||
next();
|
||||
});*/
|
||||
const socket = ws as ExSocketInterface;
|
||||
socket.userId = this.nextUserId;
|
||||
this.nextUserId++;
|
||||
|
|
|
@ -3,6 +3,7 @@ import {URL_ROOM_STARTED} from "../Enum/EnvironmentVariable";
|
|||
import {HttpRequest, HttpResponse, TemplatedApp} from "uWebSockets.js";
|
||||
import {BaseController} from "./BaseController";
|
||||
|
||||
//todo: delete this
|
||||
export class MapController extends BaseController{
|
||||
|
||||
constructor(private App : TemplatedApp) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import {PointInterface} from "./PointInterface";
|
||||
import {Identificable} from "./Identificable";
|
||||
import {TokenInterface} from "../../Controller/AuthenticateController";
|
||||
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
|
||||
import {BatchMessage, SubMessage} from "../../Messages/generated/messages_pb";
|
||||
import {WebSocket} from "uWebSockets.js"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue