diff --git a/.env.template b/.env.template index 715ebeec..0bd7bf6d 100644 --- a/.env.template +++ b/.env.template @@ -22,6 +22,10 @@ MAX_USERNAME_LENGTH=8 OPID_CLIENT_ID= OPID_CLIENT_SECRET= OPID_CLIENT_ISSUER= +OPID_CLIENT_REDIRECT_URL= +OPID_LOGIN_SCREEN_PROVIDER=http://pusher.workadventure.localhost/login-screen +OPID_PROFILE_SCREEN_PROVIDER= +DISABLE_ANONYMOUS= # If you want to have a contact page in your menu, you MUST set CONTACT_URL to the URL of the page that you want CONTACT_URL= \ No newline at end of file diff --git a/docker-compose.single-domain.yaml b/docker-compose.single-domain.yaml index 4e85d702..cd38a0f9 100644 --- a/docker-compose.single-domain.yaml +++ b/docker-compose.single-domain.yaml @@ -40,6 +40,7 @@ services: TURN_USER: "" TURN_PASSWORD: "" START_ROOM_URL: "$START_ROOM_URL" + DISABLE_ANONYMOUS: "$DISABLE_ANONYMOUS" command: yarn run start volumes: - ./front:/usr/src/app @@ -70,6 +71,9 @@ services: OPID_CLIENT_ID: $OPID_CLIENT_ID OPID_CLIENT_SECRET: $OPID_CLIENT_SECRET OPID_CLIENT_ISSUER: $OPID_CLIENT_ISSUER + OPID_CLIENT_REDIRECT_URL: $OPID_CLIENT_REDIRECT_URL + OPID_PROFILE_SCREEN_PROVIDER: $OPID_PROFILE_SCREEN_PROVIDER + DISABLE_ANONYMOUS: $DISABLE_ANONYMOUS volumes: - ./pusher:/usr/src/app labels: diff --git a/docker-compose.yaml b/docker-compose.yaml index f68ed6a0..0e22fa91 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -43,6 +43,8 @@ services: START_ROOM_URL: "$START_ROOM_URL" MAX_PER_GROUP: "$MAX_PER_GROUP" MAX_USERNAME_LENGTH: "$MAX_USERNAME_LENGTH" + DISABLE_ANONYMOUS: "$DISABLE_ANONYMOUS" + OPID_LOGIN_SCREEN_PROVIDER: "$OPID_LOGIN_SCREEN_PROVIDER" command: yarn run start volumes: - ./front:/usr/src/app @@ -71,6 +73,9 @@ services: OPID_CLIENT_ID: $OPID_CLIENT_ID OPID_CLIENT_SECRET: $OPID_CLIENT_SECRET OPID_CLIENT_ISSUER: $OPID_CLIENT_ISSUER + OPID_CLIENT_REDIRECT_URL: $OPID_CLIENT_REDIRECT_URL + OPID_PROFILE_SCREEN_PROVIDER: $OPID_PROFILE_SCREEN_PROVIDER + DISABLE_ANONYMOUS: $DISABLE_ANONYMOUS volumes: - ./pusher:/usr/src/app labels: diff --git a/front/src/Components/Menu/ContactSubMenu.svelte b/front/src/Components/Menu/ContactSubMenu.svelte index 61ecc56e..3cf1f5fb 100644 --- a/front/src/Components/Menu/ContactSubMenu.svelte +++ b/front/src/Components/Menu/ContactSubMenu.svelte @@ -1,10 +1,60 @@ - +
+
+
+

Getting started

+

+ WorkAdventure allows you to create an online space to communicate spontaneously with others. + And it all starts with creating your own space. Choose from a large selection of prefabricated maps by our team. +

+ +
+ +
+

Create your map

+

You can also create your own custom map by following the step of the documentation.

+ +
+ + +
+
diff --git a/front/src/Components/Menu/GuestSubMenu.svelte b/front/src/Components/Menu/GuestSubMenu.svelte new file mode 100644 index 00000000..13a7981a --- /dev/null +++ b/front/src/Components/Menu/GuestSubMenu.svelte @@ -0,0 +1,75 @@ + + +
+
+ +
+

Share the link of the room !

+ + +
+
+
+ + \ No newline at end of file diff --git a/front/src/Components/Menu/Menu.svelte b/front/src/Components/Menu/Menu.svelte index 4eecb370..83715304 100644 --- a/front/src/Components/Menu/Menu.svelte +++ b/front/src/Components/Menu/Menu.svelte @@ -2,11 +2,11 @@ import {fly} from "svelte/transition"; import SettingsSubMenu from "./SettingsSubMenu.svelte"; import ProfileSubMenu from "./ProfileSubMenu.svelte"; - import CreateMapSubMenu from "./CreateMapSubMenu.svelte"; import AboutRoomSubMenu from "./AboutRoomSubMenu.svelte"; import GlobalMessageSubMenu from "./GlobalMessagesSubMenu.svelte"; import ContactSubMenu from "./ContactSubMenu.svelte"; import CustomSubMenu from "./CustomSubMenu.svelte" + import GuestSubMenu from "./GuestSubMenu.svelte"; import { checkSubMenuToShow, customMenuIframe, @@ -19,21 +19,21 @@ import type {Unsubscriber} from "svelte/store"; import {sendMenuClickedEvent} from "../../Api/iframe/Ui/MenuItem"; - let activeSubMenu: string = SubMenusInterface.settings; - let activeComponent: typeof SettingsSubMenu | typeof CustomSubMenu = SettingsSubMenu; + let activeSubMenu: string = SubMenusInterface.profile; + let activeComponent: typeof ProfileSubMenu | typeof CustomSubMenu = ProfileSubMenu; let props: { url: string, allowApi: boolean }; let unsubscriberSubMenuStore: Unsubscriber; onMount(() => { unsubscriberSubMenuStore = subMenusStore.subscribe(() => { if(!get(subMenusStore).includes(activeSubMenu)) { - switchMenu(SubMenusInterface.settings); + switchMenu(SubMenusInterface.profile); } }) checkSubMenuToShow(); - switchMenu(SubMenusInterface.settings); + switchMenu(SubMenusInterface.profile); }) onDestroy(() => { @@ -52,8 +52,8 @@ case SubMenusInterface.profile: activeComponent = ProfileSubMenu; break; - case SubMenusInterface.createMap: - activeComponent = CreateMapSubMenu; + case SubMenusInterface.invite: + activeComponent = GuestSubMenu; break; case SubMenusInterface.aboutRoom: activeComponent = AboutRoomSubMenu; diff --git a/front/src/Components/Menu/ProfileSubMenu.svelte b/front/src/Components/Menu/ProfileSubMenu.svelte index 83ec329c..4d7438a2 100644 --- a/front/src/Components/Menu/ProfileSubMenu.svelte +++ b/front/src/Components/Menu/ProfileSubMenu.svelte @@ -12,6 +12,10 @@ 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"; + import btnProfileSubMenuIdentity from "../images/btn-menu-profile-identity.svg"; + import btnProfileSubMenuCompanion from "../images/btn-menu-profile-companion.svg"; + import btnProfileSubMenuWoka from "../images/btn-menu-profile-woka.svg"; function disableMenuStores(){ @@ -55,54 +59,107 @@
- {#if $userIsConnected} + + +
+ {#if $userIsConnected} +
+ {#if PROFILE_URL != undefined} + + {/if} +
+
+ +
+ {:else} +
+ Sign in +
+ {/if} +
+ + +
+
+ +
+
+ Profile validated by domain: ${domain} +
+
+ Your email: ${email} +
+
+ + + `; + } +} diff --git a/pusher/src/Enum/EnvironmentVariable.ts b/pusher/src/Enum/EnvironmentVariable.ts index ab1ce110..23d2c23f 100644 --- a/pusher/src/Enum/EnvironmentVariable.ts +++ b/pusher/src/Enum/EnvironmentVariable.ts @@ -15,6 +15,9 @@ export const FRONT_URL = process.env.FRONT_URL || "http://localhost"; export const OPID_CLIENT_ID = process.env.OPID_CLIENT_ID || ""; export const OPID_CLIENT_SECRET = process.env.OPID_CLIENT_SECRET || ""; export const OPID_CLIENT_ISSUER = process.env.OPID_CLIENT_ISSUER || ""; +export const OPID_CLIENT_REDIRECT_URL = process.env.OPID_CLIENT_REDIRECT_URL || FRONT_URL + "/jwt"; +export const OPID_PROFILE_SCREEN_PROVIDER = process.env.OPID_PROFILE_SCREEN_PROVIDER || ADMIN_URL + "/profile"; +export const DISABLE_ANONYMOUS = process.env.DISABLE_ANONYMOUS || false; export { SECRET_KEY, diff --git a/pusher/src/Services/AdminApi.ts b/pusher/src/Services/AdminApi.ts index e53d00ae..6e1848eb 100644 --- a/pusher/src/Services/AdminApi.ts +++ b/pusher/src/Services/AdminApi.ts @@ -1,4 +1,4 @@ -import { ADMIN_API_TOKEN, ADMIN_API_URL, ADMIN_URL } from "../Enum/EnvironmentVariable"; +import { ADMIN_API_TOKEN, ADMIN_API_URL, ADMIN_URL, OPID_PROFILE_SCREEN_PROVIDER } from "../Enum/EnvironmentVariable"; import Axios from "axios"; import { GameRoomPolicyTypes } from "_Model/PusherRoom"; import { CharacterTexture } from "./AdminApi/CharacterTexture"; @@ -142,13 +142,19 @@ class AdminApi { }); } - /*TODO add constant to use profile companny*/ + /** + * + * @param accessToken + */ getProfileUrl(accessToken: string): string { - if (!ADMIN_URL) { + if (!OPID_PROFILE_SCREEN_PROVIDER) { throw new Error("No admin backoffice set!"); } + return `${OPID_PROFILE_SCREEN_PROVIDER}?accessToken=${accessToken}`; + } - return ADMIN_URL + `/profile?token=${accessToken}`; + async logoutOauth(token: string) { + await Axios.get(ADMIN_API_URL + `/oauth/logout?token=${token}`); } } diff --git a/pusher/src/Services/AdminApi/MapDetailsData.ts b/pusher/src/Services/AdminApi/MapDetailsData.ts index 278b81bb..7a1f57ff 100644 --- a/pusher/src/Services/AdminApi/MapDetailsData.ts +++ b/pusher/src/Services/AdminApi/MapDetailsData.ts @@ -16,6 +16,7 @@ export const isMapDetailsData = new tg.IsInterface() tags: tg.isArray(tg.isString), textures: tg.isArray(isCharacterTexture), contactPage: tg.isUnion(tg.isString, tg.isUndefined), + authenticationMandatory: tg.isUnion(tg.isBoolean, tg.isUndefined), }) .get(); diff --git a/pusher/src/Services/JWTTokenManager.ts b/pusher/src/Services/JWTTokenManager.ts index 24393084..2f482dbf 100644 --- a/pusher/src/Services/JWTTokenManager.ts +++ b/pusher/src/Services/JWTTokenManager.ts @@ -6,13 +6,13 @@ import { adminApi, AdminBannedData } from "../Services/AdminApi"; export interface AuthTokenData { identifier: string; //will be a email if logged in or an uuid if anonymous - hydraAccessToken?: string; + accessToken?: string; } export const tokenInvalidException = "tokenInvalid"; class JWTTokenManager { - public createAuthToken(identifier: string, hydraAccessToken?: string) { - return Jwt.sign({ identifier, hydraAccessToken }, SECRET_KEY, { expiresIn: "30d" }); + public createAuthToken(identifier: string, accessToken?: string) { + return Jwt.sign({ identifier, accessToken }, SECRET_KEY, { expiresIn: "30d" }); } public verifyJWTToken(token: string, ignoreExpiration: boolean = false): AuthTokenData { diff --git a/pusher/src/Services/OpenIDClient.ts b/pusher/src/Services/OpenIDClient.ts index c9137ad5..13bf6f76 100644 --- a/pusher/src/Services/OpenIDClient.ts +++ b/pusher/src/Services/OpenIDClient.ts @@ -1,7 +1,10 @@ import { Issuer, Client, IntrospectionResponse } from "openid-client"; -import { OPID_CLIENT_ID, OPID_CLIENT_SECRET, OPID_CLIENT_ISSUER, FRONT_URL } from "../Enum/EnvironmentVariable"; - -const opidRedirectUri = FRONT_URL + "/jwt"; +import { + OPID_CLIENT_ID, + OPID_CLIENT_SECRET, + OPID_CLIENT_ISSUER, + OPID_CLIENT_REDIRECT_URL, +} from "../Enum/EnvironmentVariable"; class OpenIDClient { private issuerPromise: Promise | null = null; @@ -12,7 +15,7 @@ class OpenIDClient { return new issuer.Client({ client_id: OPID_CLIENT_ID, client_secret: OPID_CLIENT_SECRET, - redirect_uris: [opidRedirectUri], + redirect_uris: [OPID_CLIENT_REDIRECT_URL], response_types: ["code"], }); }); @@ -35,7 +38,7 @@ class OpenIDClient { public getUserInfo(code: string, nonce: string): Promise<{ email: string; sub: string; access_token: string }> { return this.initClient().then((client) => { - return client.callback(opidRedirectUri, { code }, { nonce }).then((tokenSet) => { + return client.callback(OPID_CLIENT_REDIRECT_URL, { code }, { nonce }).then((tokenSet) => { return client.userinfo(tokenSet).then((res) => { return { ...res,