diff --git a/.env.example b/.env.example index d344e5c6..b4e8a11d 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,5 @@ VITE_BASE_URI="/" VITE_API_URI="/" -VITE_NEXTCLOUD_URI="/nextcloud" VITE_AXIOS_TIMEOUT=10000 VITE_PROXY_API_URL="http://localhost:8090" diff --git a/src/main/java/fr/recia/collabsoft/configuration/bean/FrontProperties.java b/src/main/java/fr/recia/collabsoft/configuration/bean/FrontProperties.java index 88a870f7..ae72c84f 100644 --- a/src/main/java/fr/recia/collabsoft/configuration/bean/FrontProperties.java +++ b/src/main/java/fr/recia/collabsoft/configuration/bean/FrontProperties.java @@ -21,6 +21,7 @@ public class FrontProperties { private String userInfoApiUrl; + private String nextcloudUri; private CollaborationProperties collaboration = new CollaborationProperties(); private ExtendedUportalHeaderProperties extendedUportalHeader = new ExtendedUportalHeaderProperties(); private ExtendedUportalFooterProperties extendedUportalFooter = new ExtendedUportalFooterProperties(); @@ -115,6 +116,7 @@ public String toString() { public String toString() { return "\"FrontProperties\": {" + "\n\t\"userInfoApiUrl\": \"" + userInfoApiUrl + "\"," + + "\n\t\"nextcloudUri\": \"" + nextcloudUri + "\"," + "\n\t\"collaboration\": \"" + collaboration + "\"," + "\n\t\"extendedUportalHeader\": \"" + extendedUportalHeader + "\"," + "\n\t\"extendedUportalFooter\": \"" + extendedUportalFooter + "\"" + diff --git a/src/main/resources/config/application-dev.example.yml b/src/main/resources/config/application-dev.example.yml index 95171476..0912de3c 100644 --- a/src/main/resources/config/application-dev.example.yml +++ b/src/main/resources/config/application-dev.example.yml @@ -48,6 +48,8 @@ app: front: user-info-api-url: '' + nextcloud-uri: '' # You can use domain variable in case of subdomain hosting (ex: 'https://nc.${domain}') + collaboration: websocket-api-url: '' diff --git a/src/main/resources/config/application-prod.example.yml b/src/main/resources/config/application-prod.example.yml index f28173ba..73e8caa5 100644 --- a/src/main/resources/config/application-prod.example.yml +++ b/src/main/resources/config/application-prod.example.yml @@ -22,7 +22,7 @@ app: cors: enable: true allowed-origins: - - https://*.giprecia.net + - soffit: jwt-signature-key: '' @@ -33,6 +33,8 @@ app: front: user-info-api-url: '' + nextcloud-uri: '' + collaboration: websocket-api-url: '' diff --git a/src/main/resources/config/application.yml b/src/main/resources/config/application.yml index d249cbb8..8beb7efe 100644 --- a/src/main/resources/config/application.yml +++ b/src/main/resources/config/application.yml @@ -71,6 +71,8 @@ app: front: user-info-api-url: '' + nextcloud-uri: '' + collaboration: websocket-api-url: '' diff --git a/src/main/webapp/src/components/FileMenu.vue b/src/main/webapp/src/components/FileMenu.vue index a179b52e..dcf4785f 100644 --- a/src/main/webapp/src/components/FileMenu.vue +++ b/src/main/webapp/src/components/FileMenu.vue @@ -16,7 +16,7 @@ const appStore = useAppStore(); const { isApp } = storeToRefs(appStore); const configurationStore = useConfigurationStore(); -const { isSettings } = storeToRefs(configurationStore); +const { isNextcloudAvailable, isSettings } = storeToRefs(configurationStore); const fileStore = useFileStore(); const { loadFile } = fileStore; @@ -63,7 +63,7 @@ const onHistories = async (): Promise => { const onExport = async (): Promise => { await getFile(); - if (!file.value) return; + if (!file.value || !isNextcloudAvailable.value) return; await saveOnNextcloud(toFile(file.value), file.value.associatedApp.extension); }; @@ -119,6 +119,7 @@ const onDelete = async (): Promise => { @click="onHistories" /> { try { const response = await getConfiguration(); configuration.value = response.data; - await initToken(configuration.value!.front.userInfoApiUrl); - await useEntTheme(configuration.value!.front.extendedUportalHeader.templateApiPath); - await initAppsRoutes(configuration.value!.front.apps); + if (!configuration.value) return false; + if (isNextcloudAvailable.value) setNextcloudUri(configuration.value.front.nextcloudUri); + await initToken(configuration.value.front.userInfoApiUrl); + await useEntTheme(configuration.value.front.extendedUportalHeader.templateApiPath); + await initAppsRoutes(configuration.value.front.apps); return true; } catch (e) { @@ -35,6 +38,10 @@ export const useConfigurationStore = defineStore('configuration', () => { const isReady = computed(() => isInit.value && isSoffitOk.value); + /* -- Gestion de nextcloud -- */ + + const isNextcloudAvailable = computed(() => (configuration.value?.front.nextcloudUri ?? '').length > 0); + /* -- Gestion de l'utilisateur -- */ const user = ref({ sub: 'guest', token: undefined }); @@ -61,6 +68,7 @@ export const useConfigurationStore = defineStore('configuration', () => { init, isInit, isReady, + isNextcloudAvailable, user, isSoffitOk, lastNavigation, diff --git a/src/main/webapp/src/types/configurationType.ts b/src/main/webapp/src/types/configurationType.ts index b664f07c..efdf0975 100644 --- a/src/main/webapp/src/types/configurationType.ts +++ b/src/main/webapp/src/types/configurationType.ts @@ -3,6 +3,7 @@ import type { AssociatedApp } from '@/types/associatedAppType.ts'; export type Configuration = { front: { userInfoApiUrl: string; + nextcloudUri: string; collaboration: { websocketApiUrl: string; }; diff --git a/src/main/webapp/src/utils/nextcloudUtils.ts b/src/main/webapp/src/utils/nextcloudUtils.ts index cb205d97..a6fdb5be 100644 --- a/src/main/webapp/src/utils/nextcloudUtils.ts +++ b/src/main/webapp/src/utils/nextcloudUtils.ts @@ -2,22 +2,30 @@ import i18n from '@/plugins/i18n.ts'; import { saveNcFile } from '@/services/api/nextcloudService.ts'; import { useConfigurationStore } from '@/stores/configurationStore.ts'; import { errorHandler } from '@/utils/axiosUtils.ts'; +import { interpolate } from '@/utils/stringUtils.ts'; import axios from 'axios'; import { storeToRefs } from 'pinia'; import { toast } from 'vue3-toastify'; -const { VITE_NEXTCLOUD_URI, VITE_AXIOS_TIMEOUT } = import.meta.env; +const { VITE_AXIOS_TIMEOUT } = import.meta.env; const { t } = i18n.global; +let nextcloudBaseUri: string | undefined; + const instance = axios.create({ - baseURL: `${VITE_NEXTCLOUD_URI}/remote.php/dav/files/`, timeout: VITE_AXIOS_TIMEOUT, headers: { Authorization: 'Bearer null', }, }); +const setNextcloudUri = (uri: string): void => { + if (uri.length <= 0) return; + nextcloudBaseUri = interpolate(uri, { domain: window.location.hostname }); + instance.defaults.baseURL = `${nextcloudBaseUri}/remote.php/dav/files/`; +}; + const saveOnNextcloud = async (file: File, type: string): Promise => { const configurationStore = useConfigurationStore(); const { user } = storeToRefs(configurationStore); @@ -32,7 +40,7 @@ const saveOnNextcloud = async (file: File, type: string): Promise => { }), { onClick: () => { - window.open(`${VITE_NEXTCLOUD_URI}/`, '_blank'); + window.open(`${nextcloudBaseUri}/`, '_blank'); }, }, ); @@ -42,11 +50,11 @@ const saveOnNextcloud = async (file: File, type: string): Promise => { toast.error(t('toast.nextcloud.401'), { autoClose: false, onClick: () => { - window.open(`${VITE_NEXTCLOUD_URI}/apps/user_cas/login`, '_blank'); + window.open(`${nextcloudBaseUri}/apps/user_cas/login`, '_blank'); }, }); } else errorHandler(error, true); } }; -export { instance, saveOnNextcloud }; +export { instance, setNextcloudUri, saveOnNextcloud }; diff --git a/src/main/webapp/src/utils/stringUtils.ts b/src/main/webapp/src/utils/stringUtils.ts index 21981354..d2dd64c0 100644 --- a/src/main/webapp/src/utils/stringUtils.ts +++ b/src/main/webapp/src/utils/stringUtils.ts @@ -24,4 +24,11 @@ const slugify = (value: string): string => { .replace(/-+/g, '-'); // remove consecutive hyphens }; -export { capitalize, charOTP, slugify }; +const interpolate = (input: string, params: Object): string => { + const names = Object.keys(params); + const vals = Object.values(params); + + return new Function(...names, `return \`${input}\`;`)(...vals); +}; + +export { capitalize, charOTP, slugify, interpolate };