Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • bmi/opendesk/components/platform-development/charts/opendesk-jitsi
1 result
Show changes
Commits on Source (8)
Showing with 551 additions and 176 deletions
# [1.10.0](https://gitlab.opencode.de/bmi/opendesk/components/platform-development/charts/opendesk-jitsi/compare/v1.9.3...v1.10.0) (2024-09-16)
### Bug Fixes
* **body.html:** no topbar during the meeting session. It breaks UI ([c583c92](https://gitlab.opencode.de/bmi/opendesk/components/platform-development/charts/opendesk-jitsi/commit/c583c921ced0a768f036df92610b5dede7151bdf))
* **body.html:** silent login through ICS ([2cd6823](https://gitlab.opencode.de/bmi/opendesk/components/platform-development/charts/opendesk-jitsi/commit/2cd68238d663d33d4bea010c6506f43a394d69d5))
* **ics:** add ICS related parameters and configs ([b0ad493](https://gitlab.opencode.de/bmi/opendesk/components/platform-development/charts/opendesk-jitsi/commit/b0ad493c6a68288d189c88f47c56a8de56cdb38c))
### Features
* **body.html:** Add OpenDesk menu to Jitsi ([8d37ac5](https://gitlab.opencode.de/bmi/opendesk/components/platform-development/charts/opendesk-jitsi/commit/8d37ac5d5bfcc6d87f4c785027dbf2cc25b324fa))
* **portal-url:** provide the portal url for Jitsi frontend ([d81a47b](https://gitlab.opencode.de/bmi/opendesk/components/platform-development/charts/opendesk-jitsi/commit/d81a47b5646fe8790b6ea7c5c4a41b05db63bdb5))
## [1.9.3](https://gitlab.opencode.de/bmi/opendesk/components/platform-development/charts/opendesk-jitsi/compare/v1.9.2...v1.9.3) (2024-09-02) ## [1.9.3](https://gitlab.opencode.de/bmi/opendesk/components/platform-development/charts/opendesk-jitsi/compare/v1.9.2...v1.9.3) (2024-09-02)
......
...@@ -20,5 +20,5 @@ keywords: ...@@ -20,5 +20,5 @@ keywords:
- "networking" - "networking"
name: "opendesk-jitsi" name: "opendesk-jitsi"
type: "application" type: "application"
version: "1.9.3" version: "1.10.0"
... ...
...@@ -13,13 +13,13 @@ To install the chart with the release name `my-release`, you have two options: ...@@ -13,13 +13,13 @@ To install the chart with the release name `my-release`, you have two options:
### Install via Repository ### Install via Repository
```console ```console
helm repo add opendesk-jitsi https://gitlab.opencode.de/api/v4/projects/1377/packages/helm/stable helm repo add opendesk-jitsi https://gitlab.opencode.de/api/v4/projects/1377/packages/helm/stable
helm install my-release --version 1.9.3 opendesk-jitsi/opendesk-jitsi helm install my-release --version 1.10.0 opendesk-jitsi/opendesk-jitsi
``` ```
### Install via OCI Registry ### Install via OCI Registry
```console ```console
helm repo add opendesk-jitsi oci://registry.opencode.de/bmi/opendesk/components/platform-development/charts/opendesk-jitsi helm repo add opendesk-jitsi oci://registry.opencode.de/bmi/opendesk/components/platform-development/charts/opendesk-jitsi
helm install my-release --version 1.9.3 opendesk-jitsi/opendesk-jitsi helm install my-release --version 1.10.0 opendesk-jitsi/opendesk-jitsi
``` ```
## Requirements ## Requirements
...@@ -49,6 +49,7 @@ helm install my-release --version 1.9.3 opendesk-jitsi/opendesk-jitsi ...@@ -49,6 +49,7 @@ helm install my-release --version 1.9.3 opendesk-jitsi/opendesk-jitsi
| extraVolumes | list | `[]` | Optionally specify extra list of additional volumes | | extraVolumes | list | `[]` | Optionally specify extra list of additional volumes |
| fullnameOverride | string | `""` | Provide a name to substitute for the full names of resources. | | fullnameOverride | string | `""` | Provide a name to substitute for the full names of resources. |
| global.domain | string | `"souvap-univention.de"` | The Top-Level-Domain (TLD) name which is used in f.e. in Ingress component. | | global.domain | string | `"souvap-univention.de"` | The Top-Level-Domain (TLD) name which is used in f.e. in Ingress component. |
| global.hosts.intercomService | string | `"ics"` | Subdomain for ICS, results in "https://{{ intercomService }}.{{ domain }}". |
| global.hosts.keycloak | string | `"id"` | Subdomain for Keycloak, results in "https://{{ keycloak }}.{{ domain }}". | | global.hosts.keycloak | string | `"id"` | Subdomain for Keycloak, results in "https://{{ keycloak }}.{{ domain }}". |
| global.hosts.univentionCorporateServer | string | `"portal"` | Subdomain for Univention Corporate Server providing the portal. Results in "https://{{ univentionCorporateServer }}.{{ domain }}". The value is used to set the hyperlink on the watermark. | | global.hosts.univentionCorporateServer | string | `"portal"` | Subdomain for Univention Corporate Server providing the portal. Results in "https://{{ univentionCorporateServer }}.{{ domain }}". The value is used to set the hyperlink on the watermark. |
| global.imagePullSecrets | list | `[]` | Credentials to fetch images from private registry Ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ imagePullSecrets: - "docker-registry" | | global.imagePullSecrets | list | `[]` | Credentials to fetch images from private registry Ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ imagePullSecrets: - "docker-registry" |
...@@ -120,23 +121,29 @@ helm install my-release --version 1.9.3 opendesk-jitsi/opendesk-jitsi ...@@ -120,23 +121,29 @@ helm install my-release --version 1.9.3 opendesk-jitsi/opendesk-jitsi
| jitsi.web.extraVolumeMounts[1].mountPath | string | `"/config/custom-interface_config.js"` | | | jitsi.web.extraVolumeMounts[1].mountPath | string | `"/config/custom-interface_config.js"` | |
| jitsi.web.extraVolumeMounts[1].name | string | `"jitsi-meet-swp"` | | | jitsi.web.extraVolumeMounts[1].name | string | `"jitsi-meet-swp"` | |
| jitsi.web.extraVolumeMounts[1].subPath | string | `"custom-interface_config.js"` | | | jitsi.web.extraVolumeMounts[1].subPath | string | `"custom-interface_config.js"` | |
| jitsi.web.extraVolumeMounts[2].mountPath | string | `"/usr/share/jitsi-meet/images/watermark.svg"` | | | jitsi.web.extraVolumeMounts[2].mountPath | string | `"/usr/share/jitsi-meet/static/url-ics"` | |
| jitsi.web.extraVolumeMounts[2].name | string | `"jitsi-meet-swp"` | | | jitsi.web.extraVolumeMounts[2].name | string | `"jitsi-meet-swp"` | |
| jitsi.web.extraVolumeMounts[2].subPath | string | `"watermark.svg"` | | | jitsi.web.extraVolumeMounts[2].subPath | string | `"url-ics"` | |
| jitsi.web.extraVolumeMounts[3].mountPath | string | `"/usr/share/jitsi-meet/body.html"` | | | jitsi.web.extraVolumeMounts[3].mountPath | string | `"/usr/share/jitsi-meet/static/url-portal"` | |
| jitsi.web.extraVolumeMounts[3].name | string | `"jitsi-meet-swp"` | | | jitsi.web.extraVolumeMounts[3].name | string | `"jitsi-meet-swp"` | |
| jitsi.web.extraVolumeMounts[3].subPath | string | `"body.oidc.html"` | | | jitsi.web.extraVolumeMounts[3].subPath | string | `"url-portal"` | |
| jitsi.web.extraVolumeMounts[4].mountPath | string | `"/defaults/meet.conf"` | | | jitsi.web.extraVolumeMounts[4].mountPath | string | `"/usr/share/jitsi-meet/images/watermark.svg"` | |
| jitsi.web.extraVolumeMounts[4].name | string | `"jitsi-meet-swp"` | | | jitsi.web.extraVolumeMounts[4].name | string | `"jitsi-meet-swp"` | |
| jitsi.web.extraVolumeMounts[4].subPath | string | `"meet.oidc.conf"` | | | jitsi.web.extraVolumeMounts[4].subPath | string | `"watermark.svg"` | |
| jitsi.web.extraVolumeMounts[5].mountPath | string | `"/usr/share/jitsi-meet/static/oidc-adapter.html"` | | | jitsi.web.extraVolumeMounts[5].mountPath | string | `"/usr/share/jitsi-meet/body.html"` | |
| jitsi.web.extraVolumeMounts[5].name | string | `"jitsi-meet-swp"` | | | jitsi.web.extraVolumeMounts[5].name | string | `"jitsi-meet-swp"` | |
| jitsi.web.extraVolumeMounts[5].subPath | string | `"oidc-adapter.html"` | | | jitsi.web.extraVolumeMounts[5].subPath | string | `"body.html"` | |
| jitsi.web.extraVolumeMounts[6].mountPath | string | `"/usr/share/jitsi-meet/static/oidc-redirect.html"` | | | jitsi.web.extraVolumeMounts[6].mountPath | string | `"/defaults/meet.conf"` | |
| jitsi.web.extraVolumeMounts[6].name | string | `"jitsi-meet-swp"` | | | jitsi.web.extraVolumeMounts[6].name | string | `"jitsi-meet-swp"` | |
| jitsi.web.extraVolumeMounts[6].subPath | string | `"oidc-redirect.html"` | | | jitsi.web.extraVolumeMounts[6].subPath | string | `"meet.oidc.conf"` | |
| jitsi.web.extraVolumes[0].configMap.items[0].key | string | `"body.oidc.html"` | | | jitsi.web.extraVolumeMounts[7].mountPath | string | `"/usr/share/jitsi-meet/static/oidc-adapter.html"` | |
| jitsi.web.extraVolumes[0].configMap.items[0].path | string | `"body.oidc.html"` | | | jitsi.web.extraVolumeMounts[7].name | string | `"jitsi-meet-swp"` | |
| jitsi.web.extraVolumeMounts[7].subPath | string | `"oidc-adapter.html"` | |
| jitsi.web.extraVolumeMounts[8].mountPath | string | `"/usr/share/jitsi-meet/static/oidc-redirect.html"` | |
| jitsi.web.extraVolumeMounts[8].name | string | `"jitsi-meet-swp"` | |
| jitsi.web.extraVolumeMounts[8].subPath | string | `"oidc-redirect.html"` | |
| jitsi.web.extraVolumes[0].configMap.items[0].key | string | `"body.html"` | |
| jitsi.web.extraVolumes[0].configMap.items[0].path | string | `"body.html"` | |
| jitsi.web.extraVolumes[0].configMap.items[1].key | string | `"custom-config.js"` | | | jitsi.web.extraVolumes[0].configMap.items[1].key | string | `"custom-config.js"` | |
| jitsi.web.extraVolumes[0].configMap.items[1].path | string | `"custom-config.js"` | | | jitsi.web.extraVolumes[0].configMap.items[1].path | string | `"custom-config.js"` | |
| jitsi.web.extraVolumes[0].configMap.items[2].key | string | `"custom-interface_config.js"` | | | jitsi.web.extraVolumes[0].configMap.items[2].key | string | `"custom-interface_config.js"` | |
...@@ -147,8 +154,12 @@ helm install my-release --version 1.9.3 opendesk-jitsi/opendesk-jitsi ...@@ -147,8 +154,12 @@ helm install my-release --version 1.9.3 opendesk-jitsi/opendesk-jitsi
| jitsi.web.extraVolumes[0].configMap.items[4].path | string | `"oidc-adapter.html"` | | | jitsi.web.extraVolumes[0].configMap.items[4].path | string | `"oidc-adapter.html"` | |
| jitsi.web.extraVolumes[0].configMap.items[5].key | string | `"oidc-redirect.html"` | | | jitsi.web.extraVolumes[0].configMap.items[5].key | string | `"oidc-redirect.html"` | |
| jitsi.web.extraVolumes[0].configMap.items[5].path | string | `"oidc-redirect.html"` | | | jitsi.web.extraVolumes[0].configMap.items[5].path | string | `"oidc-redirect.html"` | |
| jitsi.web.extraVolumes[0].configMap.items[6].key | string | `"watermark.svg"` | | | jitsi.web.extraVolumes[0].configMap.items[6].key | string | `"url-ics"` | |
| jitsi.web.extraVolumes[0].configMap.items[6].path | string | `"watermark.svg"` | | | jitsi.web.extraVolumes[0].configMap.items[6].path | string | `"url-ics"` | |
| jitsi.web.extraVolumes[0].configMap.items[7].key | string | `"url-portal"` | |
| jitsi.web.extraVolumes[0].configMap.items[7].path | string | `"url-portal"` | |
| jitsi.web.extraVolumes[0].configMap.items[8].key | string | `"watermark.svg"` | |
| jitsi.web.extraVolumes[0].configMap.items[8].path | string | `"watermark.svg"` | |
| jitsi.web.extraVolumes[0].configMap.name | string | `"jitsi-meet-swp"` | | | jitsi.web.extraVolumes[0].configMap.name | string | `"jitsi-meet-swp"` | |
| jitsi.web.extraVolumes[0].name | string | `"jitsi-meet-swp"` | | | jitsi.web.extraVolumes[0].name | string | `"jitsi-meet-swp"` | |
| jitsi.web.image.pullPolicy | string | `"IfNotPresent"` | | | jitsi.web.image.pullPolicy | string | `"IfNotPresent"` | |
......
<!--
SPDX-FileCopyrightText: 2023 Bundesministerium des Innern und für Heimat, PG ZenDiS "Projektgruppe für Aufbau ZenDiS"
SPDX-License-Identifier: Apache-2.0
-->
<script>
// -----------------------------------------------------------------------------
// This script manages OIDC flow.
// -----------------------------------------------------------------------------
let failedAttempt = 0;
function oidcRedirect() {
const qs = new URLSearchParams(window.location.search.substring(1));
qs.delete('oidc');
const path = encodeURIComponent(window.location.pathname);
const search = encodeURIComponent(qs.toString());
const hash = encodeURIComponent(window.location.hash.substring(1));
window.location = `/oidc/auth?path=${path}&search=${search}&hash=${hash}`;
try {
// remove react from DOM to prevent UI distortion
document.all.react.remove();
} catch {
// do nothing
}
}
function interceptLoginRequest() {
try {
// if conference is already started, dont wait for an auth request
if (APP.conference.isJoined()) return;
// check if login or IamHost button is created in DOM
const _button = document.getElementById("modal-dialog-ok-button");
if (!_button) throw("button is not created yet");
let labelKey;
try {
labelKey = Object.values(_button)[0].return.memoizedProps.labelKey;
} catch {
// do nothing
}
if (labelKey === "dialog.login") {
// if this is a login screen, redirect to OIDC login page
oidcRedirect();
} else if (labelKey === "dialog.IamHost") {
// if this is an IamHost screen, redirect to OIDC login page when clicked
_button.onclick = oidcRedirect
}
} catch(e) {
failedAttempt += 1;
if (failedAttempt < 180) {
setTimeout(function() {interceptLoginRequest();}, 1000);
}
}
}
interceptLoginRequest();
</script>
<script>
// -----------------------------------------------------------------------------
// This script customizes Jitsi UI if the room is created by Element Jitsi
// Widget. It senses the room created by Element by checking its name. The room
// created by Element has a special name format:
//
// base32decode(room_name) should match RegExp("^(!.*:.*[.][a-z]*)$")
// or
// room_name should match RegExp("^(Jitsi[A-Z][a-z]{23})$")
// -----------------------------------------------------------------------------
function base32decode(s) {
const a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
const pad = "=";
const len = s.length;
const apad = a + pad;
let v, x, r=0, bits=0, c, o="";
s = s.toUpperCase();
for(i=0; i<len; i+=1) {
v = apad.indexOf(s.charAt(i));
if (v>=0 && v<32) {
x = (x << 5) | v;
bits += 5;
if (bits >= 8) {
c = (x >> (bits - 8)) & 0xff;
o = o + String.fromCharCode(c);
bits -= 8;
}
}
}
// remaining bits are < 8
if (bits>0) {
c = ((x << (8 - bits)) & 0xff) >> (8 - bits);
// Dont append a null terminator.
if (c!==0) {
o = o + String.fromCharCode(c);
}
}
return o;
}
function updateUIforElement() {
try {
if (!APP.conference.isJoined()) throw new Error("not joined yet");
try {
const roomName = APP.store.getState()["features/base/conference"].room;
const decoded = base32decode(roomName);
const reg1 = new RegExp("^(!.*:.*[.][a-z]*)$");
const reg2 = new RegExp("^(Jitsi[A-Z][a-z]{23})$");
if (!reg1.test(decoded) && !reg2.test(roomName)) {
throw new Error("not a Matrix room");
}
APP.store.getState()["features/base/config"].toolbarButtons = [
"camera",
"closedcaptions",
"desktop",
"download",
"feedback",
"filmstrip",
"fullscreen",
"hangup",
"help",
"livestreaming",
"microphone",
"mute-everyone",
"mute-video-everyone",
"participants-pane",
"profile",
"raisehand",
"security",
"select-background",
"settings",
"shareaudio",
"shortcuts",
"stats",
"tileview",
"toggle-camera",
"videoquality",
];
} catch {
// do nothing
}
} catch {
setTimeout(updateUIforElement, 1000);
}
}
updateUIforElement();
</script>
<script>
// -----------------------------------------------------------------------------
// This script manages the OpenDesk menu in Jitsi. The menu will be activated if
// Jitsi is opened as a standalone application. It will not be activated if it
// is inside an iframe (such as inside Element chat).
//
// It uses the language of the browser while getting the navigation data.
//
// This script silently refreshes the portal session by using a hidden iframe
// and uses this session while fetching the navigation data.
// -----------------------------------------------------------------------------
let ICS = "";
let PORTAL = "";
// -----------------------------------------------------------------------------
// Get the ICS URL from Jitsi setup and set it as a global variable.
// -----------------------------------------------------------------------------
async function setIcsUrl() {
try {
const url = "/static/url-ics";
const res = await fetch(url);
ICS = await res.text();
} catch {
// Do nothing
}
}
// -----------------------------------------------------------------------------
// Get the portal URL from Jitsi setup and set it as a global variable.
// -----------------------------------------------------------------------------
async function setPortalUrl() {
try {
const url = "/static/url-portal";
const res = await fetch(url);
PORTAL = await res.text();
} catch {
// Do nothing
}
}
// -----------------------------------------------------------------------------
// Get the navigation data
// -----------------------------------------------------------------------------
async function getNavigation() {
try {
// Get the browser language.
let lang = navigator.language || "de-DE";
if (lang === "de") lang = "de-DE";
if (lang === "en") lang = "en-US";
const url = `${ICS}/navigation.json?language=${lang}`;
const res = await fetch(url, {
credentials: "include",
headers: {
Accept: "application/json",
},
});
return await res.json();
} catch {
return {};
}
}
// -----------------------------------------------------------------------------
// Toggle menu. It will be triggered after clicking the menu icon.
// -----------------------------------------------------------------------------
function _toggleMenu() {
try {
const menu = document.getElementById("opendeskMenu");
if (menu.style.display !== "block") {
menu.style.display = "block";
} else {
menu.style.display = "none";
}
} catch {
// Do nothing
}
}
// -----------------------------------------------------------------------------
// Return the html content of the category (menu items of category)
// -----------------------------------------------------------------------------
function getCategoryItems(entries) {
try {
let items = "";
for (const entry of entries) {
items += `
<div style="display: flex; align-items:center; gap:16px; padding:8px;
font-size:14;"
>
<img src="${entry.icon_url}" height="20px" style="margin-left:12px;">
<a href="${entry.link}" target="${entry.target}"
style="text-decoration:none; font-weight:normal; color:#1F1F1F;">
${entry.display_name}
</a>
</div>
`;
}
return items;
} catch {
return "";
}
}
// -----------------------------------------------------------------------------
// Return the hmtl content of the navigation menu
// -----------------------------------------------------------------------------
function getMenuItems(nav) {
try {
// Skip if no portal session (anonymous user).
const identifier = nav.categories?.[0]?.identifier;
if (!identifier || identifier === "swp.anonymous") {
throw new Error("no item");
}
let items = "";
for (const cat of nav.categories) {
// Category title in menu.
items += `
<div style="font-size:17; font-weight:700; letter-spacing: 0.05em;
padding:16px 60px 4px 12px;"
>${cat.display_name}</div>
`;
// Category content (links) in menu.
items += getCategoryItems(cat.entries);
}
return items;
} catch {
return "";
}
}
// -----------------------------------------------------------------------------
// Create the navigation menu
// -----------------------------------------------------------------------------
function createNavigationMenu(nav) {
try {
const menuItems = getMenuItems(nav);
const menu = `
<button id="opendeskMenuButton" tabindex="0" onclick="_toggleMenu()"
aria-label="Toogle menu" style="background:none; border:none;"
>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" width="24px"
viewBox="0 0 24 24" fill="#000000" style="margin:12px 8px;"
>
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4zm6
0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0
6h4v-4h-4v4z"/>
</svg>
<div id="opendeskMenu"
style="position:absolute; top:63px; left:8px; z-index:10;
padding: 4px; background-color:white; color:#1F1F1F;
border-radius: 4px; border: 1px solid; border-color:#e8e6e3;
box-shadow: rgba(118, 131, 156, 0.6) 4px 4px 12px 0px;
text-align:left; cursor: default; display:none;"
>${menuItems}</div>
</button>
`;
// Close menu if clicked somewhere else.
document.addEventListener("click", (event) => {
try {
// Skip if clicked to the menu button or to the menu.
const menuButton = document.getElementById("opendeskMenuButton");
if (menuButton.contains(event.target)) return;
// Close menu if already visible.
const menu = document.getElementById("opendeskMenu");
if (menu.style.display !== "none") menu.style.display = "none";
} catch {
// Do nothing
}
});
return menu;
} catch {
return "";
}
}
// -----------------------------------------------------------------------------
// Create topbar
// -----------------------------------------------------------------------------
function createTopbar(nav) {
try {
// Remove topbar if exists to prevent duplicated topbars. Redirection in
// iframe may trigger the onload event again. So, we dont want to keep the
// old topbar since it will be created again.
const el = document.getElementById("opendeskTopbar");
if (el) el.remove();
// Create topbar
const topDiv = document.createElement("div");
topDiv.id = "opendeskTopbar";
topDiv.style.gap = "14px";
topDiv.style.height = "63px";
topDiv.style.display = "flex";
topDiv.style.alignItems = "center";
topDiv.style.backgroundColor = "white";
topDiv.innerHTML = `
<a href="${PORTAL}" tabindex="0" target="_blank" aria-label="Show portal"
style="margin-left:16px"
>
<img src="${PORTAL}/univention/portal/icons/logos/domain.svg"
style="width:82px; margin:16px 8px;"
alt="OpenDesk">
</a>
`;
// If the navigation data exists then add the navigation menu.
const identifier = nav.categories?.[0]?.identifier;
if (identifier && identifier !== "swp.anonymous") {
topDiv.innerHTML += createNavigationMenu(nav);
}
document.body.insertBefore(topDiv, document.body.firstChild);
} catch {
// Do nothing
}
}
// -----------------------------------------------------------------------------
// Remove the hidden iframe after refreshing the portal session
// -----------------------------------------------------------------------------
function removeIframe() {
try {
const el = document.getElementById("opendeskIframe");
if (el) el.remove();
} catch {
// Do nothing
}
}
// -----------------------------------------------------------------------------
// Try refreshing the session and recreate topbar
// -----------------------------------------------------------------------------
function recreateTopbarAfterSilentLogin() {
try {
// Silent login inside a hidden iframe and refresh the session.
const iframe = document.createElement("iframe");
iframe.id = "opendeskIframe";
iframe.src = `${ICS}/silent`;
iframe.style.display = "none";
document.body.appendChild(iframe);
// After refreshing, try to get the navigation data again and recreate
// topbar. Still no navigation data, skip it.
iframe.onload = async () => {
const nav = await getNavigation();
const identifier = nav.categories?.[0]?.identifier;
if (identifier && identifier !== "swp.anonymous") createTopbar(nav);
// Wait a bit before removing the iframe. There will be multiple onload
// events because of redirections.
setTimeout(removeIframe, 10000);
};
} catch {
// Do nothing
}
}
// -----------------------------------------------------------------------------
// Remove topbar after joining the meeting. Topbar breaks Jitsi UI if it is
// visible during the session.
// -----------------------------------------------------------------------------
function removeTopbarAfterJoining() {
try {
// Dont continue if no Jitsi session yet.
if (!APP.conference.isJoined()) throw new Error("no session yet");
// Remove topbar since the session started.
const el = document.getElementById("opendeskTopbar");
if (el) el.remove();
} catch {
// Try again after a while.
setTimeout(removeTopbarAfterJoining, 1000);
}
}
// -----------------------------------------------------------------------------
// Add topbar
// -----------------------------------------------------------------------------
async function addTopbar() {
try {
// Set the ICS URL as a global variable (ICS)
await setIcsUrl();
if (!ICS) throw new Error("unknown ics url");
// Set the portal URL as a global variable (PORTAL)
await setPortalUrl();
if (!PORTAL) throw new Error("unknown portal url");
// Trigger the event listener which will remove topbar after joining the
// meeting. Dont show the toolbar during the meeting session.
removeTopbarAfterJoining();
// Create the topbar (initially without navigation data). We want the topbar
// immediately even the navigation data is not available yet.
createTopbar({});
// Recreate the topbar after silent login.
recreateTopbarAfterSilentLogin();
} catch {
// Do nothing
}
}
// -----------------------------------------------------------------------------
// Main
// -----------------------------------------------------------------------------
// Add topbar if this is a standalone window (not an iframe)
if (!self.name || self.name === "tab_realtime_videoconference") addTopbar();
</script>
<!--
SPDX-FileCopyrightText: 2023 Bundesministerium des Innern und für Heimat, PG ZenDiS "Projektgruppe für Aufbau ZenDiS"
SPDX-License-Identifier: Apache-2.0
-->
<script>
let failedAttempt = 0;
function base32decode(s) {
const a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
const pad = "=";
const len = s.length;
const apad = a + pad;
let v, x, r=0, bits=0, c, o="";
s = s.toUpperCase();
for(i=0; i<len; i+=1) {
v = apad.indexOf(s.charAt(i));
if (v>=0 && v<32) {
x = (x << 5) | v;
bits += 5;
if (bits >= 8) {
c = (x >> (bits - 8)) & 0xff;
o = o + String.fromCharCode(c);
bits -= 8;
}
}
}
// remaining bits are < 8
if (bits>0) {
c = ((x << (8 - bits)) & 0xff) >> (8 - bits);
// Dont append a null terminator.
if (c!==0) {
o = o + String.fromCharCode(c);
}
}
return o;
}
function oidcRedirect() {
const qs = new URLSearchParams(window.location.search.substring(1));
qs.delete('oidc');
const path = encodeURIComponent(window.location.pathname);
const search = encodeURIComponent(qs.toString());
const hash = encodeURIComponent(window.location.hash.substring(1));
window.location = `/oidc/auth?path=${path}&search=${search}&hash=${hash}`;
try {
// remove react from DOM to prevent UI distortion
document.all.react.remove();
} catch {
// do nothing
}
}
function interceptLoginRequest() {
try {
// if conference is already started, dont wait for an auth request
if (APP.conference.isJoined()) return;
// check if login or IamHost button is created in DOM
const _button = document.getElementById("modal-dialog-ok-button");
if (!_button) throw("button is not created yet");
let labelKey;
try {
labelKey = Object.values(_button)[0].return.memoizedProps.labelKey;
} catch {
// do nothing
}
if (labelKey === "dialog.login") {
// if this is a login screen, redirect to OIDC login page
oidcRedirect();
} else if (labelKey === "dialog.IamHost") {
// if this is an IamHost screen, redirect to OIDC login page when clicked
_button.onclick = oidcRedirect
}
} catch(e) {
failedAttempt += 1;
if (failedAttempt < 180) {
setTimeout(function() {interceptLoginRequest();}, 1000);
}
}
}
// This function customizes Jitsi UI if the room is created by Element Jitsi
// Widget. It senses the room created by Element by checking its name. The room
// created by Element has a special name format:
//
// base32decode(room_name) should match RegExp("^(!.*:.*[.][a-z]*)$")
// or
// room_name should match RegExp("^(Jitsi[A-Z][a-z]{23})$")
function updateUIforElement() {
try {
if (!APP.conference.isJoined()) throw new Error("not joined yet");
try {
const roomName = APP.store.getState()["features/base/conference"].room;
const decoded = base32decode(roomName);
const reg1 = new RegExp("^(!.*:.*[.][a-z]*)$");
const reg2 = new RegExp("^(Jitsi[A-Z][a-z]{23})$");
if (!reg1.test(decoded) && !reg2.test(roomName)) {
throw new Error("not a Matrix room");
}
APP.store.getState()["features/base/config"].toolbarButtons = [
"camera",
"closedcaptions",
"desktop",
"download",
"feedback",
"filmstrip",
"fullscreen",
"hangup",
"help",
"livestreaming",
"microphone",
"mute-everyone",
"mute-video-everyone",
"participants-pane",
"profile",
"raisehand",
"security",
"select-background",
"settings",
"shareaudio",
"shortcuts",
"stats",
"tileview",
"toggle-camera",
"videoquality",
];
} catch {
// do nothing
}
} catch {
setTimeout(updateUIforElement, 1000);
}
}
interceptLoginRequest();
updateUIforElement();
</script>
...@@ -8,14 +8,18 @@ apiVersion: "v1" ...@@ -8,14 +8,18 @@ apiVersion: "v1"
metadata: metadata:
name: "jitsi-meet-swp" name: "jitsi-meet-swp"
data: data:
url-ics: |
https://{{- .Values.global.hosts.intercomService}}.{{ .Values.global.domain }}
url-portal: |
https://{{- .Values.global.hosts.univentionCorporateServer}}.{{ .Values.global.domain }}
watermark.svg: | watermark.svg: |
{{ .Values.theme.imagery.logoHeaderSvgWhite }} {{ .Values.theme.imagery.logoHeaderSvgWhite }}
{{ (.Files.Glob "files/web/oidc/body.oidc.html").AsConfig | nindent 2 }} {{ (.Files.Glob "files/web/body.html").AsConfig | nindent 2 }}
{{ (.Files.Glob "files/web/oidc/meet.oidc.conf").AsConfig | nindent 2 }} {{ (.Files.Glob "files/web/meet.oidc.conf").AsConfig | nindent 2 }}
{{ (.Files.Glob "files/web/oidc/oidc-adapter.html").AsConfig | nindent 2 }} {{ (.Files.Glob "files/web/oidc-adapter.html").AsConfig | nindent 2 }}
{{ (.Files.Glob "files/web/oidc/oidc-redirect.html").AsConfig | nindent 2 }} {{ (.Files.Glob "files/web/oidc-redirect.html").AsConfig | nindent 2 }}
{{ (.Files.Glob "files/web/swp/custom-config.js").AsConfig | nindent 2 }} {{ (.Files.Glob "files/web/custom-config.js").AsConfig | nindent 2 }}
{{ tpl ((.Files.Glob "files/web/swp/custom-interface_config.js").AsConfig) . | nindent 2 }} {{ tpl ((.Files.Glob "files/web/custom-interface_config.js").AsConfig) . | nindent 2 }}
{{- if and .Values.jitsi.jvb.service.enabled .Values.patchJVB.enabled }} {{- if and .Values.jitsi.jvb.service.enabled .Values.patchJVB.enabled }}
--- ---
kind: "ConfigMap" kind: "ConfigMap"
......
...@@ -8,6 +8,8 @@ global: ...@@ -8,6 +8,8 @@ global:
# Define the Subdomain for components used in f.e. in Ingress component. # Define the Subdomain for components used in f.e. in Ingress component.
hosts: hosts:
# -- Subdomain for ICS, results in "https://{{ intercomService }}.{{ domain }}".
intercomService: "ics"
# -- Subdomain for Keycloak, results in "https://{{ keycloak }}.{{ domain }}". # -- Subdomain for Keycloak, results in "https://{{ keycloak }}.{{ domain }}".
keycloak: "id" keycloak: "id"
# -- Subdomain for Univention Corporate Server providing the portal. # -- Subdomain for Univention Corporate Server providing the portal.
...@@ -225,8 +227,8 @@ jitsi: ...@@ -225,8 +227,8 @@ jitsi:
configMap: configMap:
name: "jitsi-meet-swp" name: "jitsi-meet-swp"
items: items:
- key: "body.oidc.html" - key: "body.html"
path: "body.oidc.html" path: "body.html"
- key: "custom-config.js" - key: "custom-config.js"
path: "custom-config.js" path: "custom-config.js"
- key: "custom-interface_config.js" - key: "custom-interface_config.js"
...@@ -237,6 +239,10 @@ jitsi: ...@@ -237,6 +239,10 @@ jitsi:
path: "oidc-adapter.html" path: "oidc-adapter.html"
- key: "oidc-redirect.html" - key: "oidc-redirect.html"
path: "oidc-redirect.html" path: "oidc-redirect.html"
- key: "url-ics"
path: "url-ics"
- key: "url-portal"
path: "url-portal"
- key: "watermark.svg" - key: "watermark.svg"
path: "watermark.svg" path: "watermark.svg"
extraVolumeMounts: extraVolumeMounts:
...@@ -246,12 +252,18 @@ jitsi: ...@@ -246,12 +252,18 @@ jitsi:
- name: "jitsi-meet-swp" - name: "jitsi-meet-swp"
mountPath: "/config/custom-interface_config.js" mountPath: "/config/custom-interface_config.js"
subPath: "custom-interface_config.js" subPath: "custom-interface_config.js"
- name: "jitsi-meet-swp"
mountPath: "/usr/share/jitsi-meet/static/url-ics"
subPath: "url-ics"
- name: "jitsi-meet-swp"
mountPath: "/usr/share/jitsi-meet/static/url-portal"
subPath: "url-portal"
- name: "jitsi-meet-swp" - name: "jitsi-meet-swp"
mountPath: "/usr/share/jitsi-meet/images/watermark.svg" mountPath: "/usr/share/jitsi-meet/images/watermark.svg"
subPath: "watermark.svg" subPath: "watermark.svg"
- name: "jitsi-meet-swp" - name: "jitsi-meet-swp"
mountPath: "/usr/share/jitsi-meet/body.html" mountPath: "/usr/share/jitsi-meet/body.html"
subPath: "body.oidc.html" subPath: "body.html"
- name: "jitsi-meet-swp" - name: "jitsi-meet-swp"
mountPath: "/defaults/meet.conf" mountPath: "/defaults/meet.conf"
subPath: "meet.oidc.conf" subPath: "meet.oidc.conf"
......

Consent

On this website, we use the web analytics service Matomo to analyze and review the use of our website. Through the collected statistics, we can improve our offerings and make them more appealing for you. Here, you can decide whether to allow us to process your data and set corresponding cookies for these purposes, in addition to technically necessary cookies. Further information on data protection—especially regarding "cookies" and "Matomo"—can be found in our privacy policy. You can withdraw your consent at any time.