Release 1.4.14 (#1370)
* New version of cache management (#1365) Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Exit scene acess denied detected (#1369) * Add auth token user to get right in admin and check if user have right Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Update error show Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Update token generation (#1372) - Permit only decode token to get map details, - If user have token expired, set the token to null and reload the page. This feature will be updated when authentication stategy will be finished. Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com>
This commit is contained in:
parent
45a56c2e02
commit
005a3c5a0d
2
front/dist/service-worker-prod.js
vendored
2
front/dist/service-worker-prod.js
vendored
@ -1,4 +1,4 @@
|
|||||||
let CACHE_NAME = 'workavdenture-cache-v1.2';
|
let CACHE_NAME = 'workavdenture-cache-v1.4.14';
|
||||||
let urlsToCache = [
|
let urlsToCache = [
|
||||||
'/'
|
'/'
|
||||||
];
|
];
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
let isMobile : boolean|null;
|
let isMobile : boolean|null;
|
||||||
const unsubscribe = obtainedMediaConstraintIsMobileStore.subscribe(value => {
|
const unsubscribe = obtainedMediaConstraintIsMobileStore.subscribe(value => {
|
||||||
console.log('unsubscribe => obtainedMediaConstraintIsMobileStore', value);
|
|
||||||
isMobile = value;
|
isMobile = value;
|
||||||
});
|
});
|
||||||
onDestroy(unsubscribe);
|
onDestroy(unsubscribe);
|
||||||
|
@ -29,11 +29,24 @@ class ConnectionManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadOpenIDScreen() {
|
/**
|
||||||
localUserStore.setAuthToken(null);
|
* @return Promise<void>
|
||||||
|
*/
|
||||||
|
public loadOpenIDScreen(): Promise<void> {
|
||||||
const state = localUserStore.generateState();
|
const state = localUserStore.generateState();
|
||||||
const nonce = localUserStore.generateNonce();
|
const nonce = localUserStore.generateNonce();
|
||||||
window.location.assign(`http://${PUSHER_URL}/login-screen?state=${state}&nonce=${nonce}`);
|
localUserStore.setAuthToken(null);
|
||||||
|
|
||||||
|
//TODO refactor this and don't realise previous call
|
||||||
|
return Axios.get(`http://${PUSHER_URL}/login-screen?state=${state}&nonce=${nonce}`)
|
||||||
|
.then(() => {
|
||||||
|
window.location.assign(`http://${PUSHER_URL}/login-screen?state=${state}&nonce=${nonce}`);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err, "We don't have URL to regenerate authentication user");
|
||||||
|
//TODO show modal login
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public logout() {
|
public logout() {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import Axios from "axios";
|
import Axios from "axios";
|
||||||
import { PUSHER_URL } from "../Enum/EnvironmentVariable";
|
import { PUSHER_URL } from "../Enum/EnvironmentVariable";
|
||||||
import type { CharacterTexture } from "./LocalUser";
|
import type { CharacterTexture } from "./LocalUser";
|
||||||
|
import { localUserStore } from "./LocalUserStore";
|
||||||
|
|
||||||
export class MapDetail {
|
export class MapDetail {
|
||||||
constructor(public readonly mapUrl: string, public readonly textures: CharacterTexture[] | undefined) {}
|
constructor(public readonly mapUrl: string, public readonly textures: CharacterTexture[] | undefined) {}
|
||||||
@ -87,6 +88,7 @@ export class Room {
|
|||||||
const result = await Axios.get(`${PUSHER_URL}/map`, {
|
const result = await Axios.get(`${PUSHER_URL}/map`, {
|
||||||
params: {
|
params: {
|
||||||
playUri: this.roomUrl.toString(),
|
playUri: this.roomUrl.toString(),
|
||||||
|
authToken: localUserStore.getAuthToken(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@ import { userIsAdminStore } from "../../Stores/GameStore";
|
|||||||
import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore";
|
import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore";
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
import { EmbeddedWebsiteManager } from "./EmbeddedWebsiteManager";
|
import { EmbeddedWebsiteManager } from "./EmbeddedWebsiteManager";
|
||||||
|
import { helpCameraSettingsVisibleStore } from "../../Stores/HelpCameraSettingsStore";
|
||||||
|
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
initPosition: PointInterface | null;
|
initPosition: PointInterface | null;
|
||||||
@ -814,13 +815,24 @@ export class GameScene extends DirtyScene {
|
|||||||
|
|
||||||
private triggerOnMapLayerPropertyChange() {
|
private triggerOnMapLayerPropertyChange() {
|
||||||
this.gameMap.onPropertyChange("exitSceneUrl", (newValue, oldValue) => {
|
this.gameMap.onPropertyChange("exitSceneUrl", (newValue, oldValue) => {
|
||||||
if (newValue)
|
if (newValue) {
|
||||||
this.onMapExit(
|
this.onMapExit(
|
||||||
Room.getRoomPathFromExitSceneUrl(newValue as string, window.location.toString(), this.MapUrlFile)
|
Room.getRoomPathFromExitSceneUrl(newValue as string, window.location.toString(), this.MapUrlFile)
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
setTimeout(() => {
|
||||||
|
layoutManagerActionStore.removeAction("roomAccessDenied");
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.gameMap.onPropertyChange("exitUrl", (newValue, oldValue) => {
|
this.gameMap.onPropertyChange("exitUrl", (newValue, oldValue) => {
|
||||||
if (newValue) this.onMapExit(Room.getRoomPathFromExitUrl(newValue as string, window.location.toString()));
|
if (newValue) {
|
||||||
|
this.onMapExit(Room.getRoomPathFromExitUrl(newValue as string, window.location.toString()));
|
||||||
|
} else {
|
||||||
|
setTimeout(() => {
|
||||||
|
layoutManagerActionStore.removeAction("roomAccessDenied");
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.gameMap.onPropertyChange("openWebsite", (newValue, oldValue, allProps) => {
|
this.gameMap.onPropertyChange("openWebsite", (newValue, oldValue, allProps) => {
|
||||||
if (newValue === undefined) {
|
if (newValue === undefined) {
|
||||||
@ -1290,6 +1302,18 @@ ${escapedMessage}
|
|||||||
targetRoom = await Room.createRoom(roomUrl);
|
targetRoom = await Room.createRoom(roomUrl);
|
||||||
} catch (e /*: unknown*/) {
|
} catch (e /*: unknown*/) {
|
||||||
console.error('Error while fetching new room "' + roomUrl.toString() + '"', e);
|
console.error('Error while fetching new room "' + roomUrl.toString() + '"', e);
|
||||||
|
|
||||||
|
//show information room access denied
|
||||||
|
layoutManagerActionStore.addAction({
|
||||||
|
uuid: "roomAccessDenied",
|
||||||
|
type: "warning",
|
||||||
|
message: "Room access denied. You don't have right to access on this room.",
|
||||||
|
callback: () => {
|
||||||
|
layoutManagerActionStore.removeAction("roomAccessDenied");
|
||||||
|
},
|
||||||
|
userInputManager: this.userInputManager,
|
||||||
|
});
|
||||||
|
|
||||||
this.mapTransitioning = false;
|
this.mapTransitioning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { gameManager } from "../Game/GameManager";
|
import { gameManager } from "../Game/GameManager";
|
||||||
import { Scene } from "phaser";
|
import { Scene } from "phaser";
|
||||||
import { ErrorScene } from "../Reconnecting/ErrorScene";
|
import { ErrorScene, ErrorSceneName } from "../Reconnecting/ErrorScene";
|
||||||
import { WAError } from "../Reconnecting/WAError";
|
import { WAError } from "../Reconnecting/WAError";
|
||||||
import { waScaleManager } from "../Services/WaScaleManager";
|
import { waScaleManager } from "../Services/WaScaleManager";
|
||||||
|
|
||||||
@ -36,6 +36,17 @@ export class EntryScene extends Scene {
|
|||||||
),
|
),
|
||||||
this.scene
|
this.scene
|
||||||
);
|
);
|
||||||
|
} else if (err.response && err.response.status == 403) {
|
||||||
|
ErrorScene.showError(
|
||||||
|
new WAError(
|
||||||
|
"Connection rejected",
|
||||||
|
"You cannot join the World. Try again later" +
|
||||||
|
(err.response.data ? ". \n\r \n\r" + `${err.response.data}` : "") +
|
||||||
|
".",
|
||||||
|
"If you want more information, you may contact administrator or contact us at: hello@workadventu.re"
|
||||||
|
),
|
||||||
|
this.scene
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
ErrorScene.showError(err, this.scene);
|
ErrorScene.showError(err, this.scene);
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,11 @@ export class ErrorScene extends Phaser.Scene {
|
|||||||
// Axios HTTP error
|
// Axios HTTP error
|
||||||
// client received an error response (5xx, 4xx)
|
// client received an error response (5xx, 4xx)
|
||||||
scene.start(ErrorSceneName, {
|
scene.start(ErrorSceneName, {
|
||||||
title: "HTTP " + error.response.status + " - " + error.response.statusText,
|
title:
|
||||||
|
"HTTP " +
|
||||||
|
error.response.status +
|
||||||
|
" - " +
|
||||||
|
(error.response.data ? error.response.data : error.response.statusText),
|
||||||
subTitle: "An error occurred while accessing URL:",
|
subTitle: "An error occurred while accessing URL:",
|
||||||
message: error.response.config.url,
|
message: error.response.config.url,
|
||||||
});
|
});
|
||||||
|
@ -29,7 +29,12 @@ export class BaseController {
|
|||||||
if (e.response) {
|
if (e.response) {
|
||||||
res.writeStatus(e.response.status + " " + e.response.statusText);
|
res.writeStatus(e.response.status + " " + e.response.statusText);
|
||||||
this.addCorsHeaders(res);
|
this.addCorsHeaders(res);
|
||||||
res.end("An error occurred: " + e.response.status + " " + e.response.statusText);
|
res.end(
|
||||||
|
"An error occurred: " +
|
||||||
|
e.response.status +
|
||||||
|
" " +
|
||||||
|
(e.response.data && e.response.data.message ? e.response.data.message : e.response.statusText)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
res.writeStatus("500 Internal Server Error");
|
res.writeStatus("500 Internal Server Error");
|
||||||
this.addCorsHeaders(res);
|
this.addCorsHeaders(res);
|
||||||
|
@ -174,7 +174,7 @@ export class IoSocketController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const tokenData =
|
const tokenData =
|
||||||
token && typeof token === "string" ? jwtTokenManager.decodeJWTToken(token) : null;
|
token && typeof token === "string" ? jwtTokenManager.verifyJWTToken(token) : null;
|
||||||
const userIdentifier = tokenData ? tokenData.identifier : "";
|
const userIdentifier = tokenData ? tokenData.identifier : "";
|
||||||
|
|
||||||
let memberTags: string[] = [];
|
let memberTags: string[] = [];
|
||||||
|
@ -5,6 +5,9 @@ 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";
|
import { MapDetailsData } from "../Services/AdminApi/MapDetailsData";
|
||||||
|
import { socketManager } from "../Services/SocketManager";
|
||||||
|
import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager";
|
||||||
|
import { v4 } from "uuid";
|
||||||
|
|
||||||
export class MapController extends BaseController {
|
export class MapController extends BaseController {
|
||||||
constructor(private App: TemplatedApp) {
|
constructor(private App: TemplatedApp) {
|
||||||
@ -67,7 +70,20 @@ export class MapController extends BaseController {
|
|||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const mapDetails = await adminApi.fetchMapDetails(query.playUri as string);
|
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) {
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const mapDetails = await adminApi.fetchMapDetails(query.playUri as string, userId);
|
||||||
|
|
||||||
res.writeStatus("200 OK");
|
res.writeStatus("200 OK");
|
||||||
this.addCorsHeaders(res);
|
this.addCorsHeaders(res);
|
||||||
|
@ -31,13 +31,19 @@ export interface FetchMemberDataByUuidResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AdminApi {
|
class AdminApi {
|
||||||
async fetchMapDetails(playUri: string): Promise<MapDetailsData | RoomRedirect> {
|
/**
|
||||||
|
* @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) {
|
if (!ADMIN_API_URL) {
|
||||||
return Promise.reject(new Error("No admin backoffice set!"));
|
return Promise.reject(new Error("No admin backoffice set!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
const params: { playUri: string } = {
|
const params: { playUri: string; userId?: string } = {
|
||||||
playUri,
|
playUri,
|
||||||
|
userId,
|
||||||
};
|
};
|
||||||
|
|
||||||
const res = await Axios.get(ADMIN_API_URL + "/api/map", {
|
const res = await Axios.get(ADMIN_API_URL + "/api/map", {
|
||||||
|
@ -15,9 +15,9 @@ class JWTTokenManager {
|
|||||||
return Jwt.sign({ identifier }, SECRET_KEY, { expiresIn: "200d" });
|
return Jwt.sign({ identifier }, SECRET_KEY, { expiresIn: "200d" });
|
||||||
}
|
}
|
||||||
|
|
||||||
public decodeJWTToken(token: string): AuthTokenData {
|
public verifyJWTToken(token: string, ignoreExpiration: boolean = false): AuthTokenData {
|
||||||
try {
|
try {
|
||||||
return Jwt.verify(token, SECRET_KEY, { ignoreExpiration: false }) as AuthTokenData;
|
return Jwt.verify(token, SECRET_KEY, { ignoreExpiration }) as AuthTokenData;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw { reason: tokenInvalidException, message: e.message };
|
throw { reason: tokenInvalidException, message: e.message };
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user