Merge branch 'develop'
Some checks failed
Backend tests / Linux without plugins (push) Has been cancelled
Backend tests / Linux with Plugins (push) Has been cancelled
Backend tests / Windows without plugins (push) Has been cancelled
Backend tests / Windows with Plugins (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
Frontend admin tests powered by Sauce Labs / with plugins (push) Has been cancelled
Frontend tests powered by Sauce Labs / Playwright Chrome (push) Has been cancelled
Frontend tests powered by Sauce Labs / Playwright Firefox (push) Has been cancelled
Frontend tests powered by Sauce Labs / Playwright Webkit (push) Has been cancelled
Loadtest / without plugins (push) Has been cancelled
Loadtest / with Plugins (push) Has been cancelled
Loadtest / long running (push) Has been cancelled
Perform type checks / perform type check (push) Has been cancelled
rate limit / test (push) Has been cancelled
Upgrade from latest release / Linux with Plugins (push) Has been cancelled
Windows Build / Build .zip (push) Has been cancelled

This commit is contained in:
SamTV12345 2025-04-06 15:27:01 +02:00
commit 3a9e126866
26 changed files with 3181 additions and 3125 deletions

View file

@ -53,7 +53,7 @@ jobs:
run: pnpm config set auto-install-peers false run: pnpm config set auto-install-peers false
- -
name: Install libreoffice name: Install libreoffice
uses: awalsh128/cache-apt-pkgs-action@v1.4.2 uses: awalsh128/cache-apt-pkgs-action@v1.5.0
with: with:
packages: libreoffice libreoffice-pdfimport packages: libreoffice libreoffice-pdfimport
version: 1.0 version: 1.0
@ -113,7 +113,7 @@ jobs:
run: pnpm config set auto-install-peers false run: pnpm config set auto-install-peers false
- -
name: Install libreoffice name: Install libreoffice
uses: awalsh128/cache-apt-pkgs-action@v1.4.2 uses: awalsh128/cache-apt-pkgs-action@v1.5.0
with: with:
packages: libreoffice libreoffice-pdfimport packages: libreoffice libreoffice-pdfimport
version: 1.0 version: 1.0

View file

@ -43,7 +43,7 @@ jobs:
- name: Only install direct dependencies - name: Only install direct dependencies
run: pnpm config set auto-install-peers false run: pnpm config set auto-install-peers false
- name: Install libreoffice - name: Install libreoffice
uses: awalsh128/cache-apt-pkgs-action@v1.4.2 uses: awalsh128/cache-apt-pkgs-action@v1.5.0
with: with:
packages: libreoffice libreoffice-pdfimport packages: libreoffice libreoffice-pdfimport
version: 1.0 version: 1.0
@ -62,7 +62,7 @@ jobs:
run: pnpm config set auto-install-peers false run: pnpm config set auto-install-peers false
- -
name: Install libreoffice name: Install libreoffice
uses: awalsh128/cache-apt-pkgs-action@v1.4.2 uses: awalsh128/cache-apt-pkgs-action@v1.5.0
with: with:
packages: libreoffice libreoffice-pdfimport packages: libreoffice libreoffice-pdfimport
version: 1.0 version: 1.0

View file

@ -1,3 +1,18 @@
# 2.3.0
### Notable enhancements and fixes
- Added possibility to cluster Etherpads behind reverse proxy. There is now a new reverse proxy designed for Etherpads that handles multiple Etherpads and the created pads in them. It will assign the pad assignement to an Etherpad at random but once the choice was made it will always reverse proxy the same backend. This allows to host multiple concurrent Etherpads and benefit from multi core systems even though one Etherpad is singlethreaded.
- Added reverse proxy configuration for replacing Nginx. In the past there were some issues with nginx and its configuration. This reverse proxy allows you to handle your configuration with ease.
If you want to find out more about the reverse proxy method check out the repository https://github.com/ether/etherpad-proxy . It also contains a sample docker-compose file with three Etherpads and one etherpad-proxy. Of course you need to adapt the settings.json.template to your liking and map it into the reverse proxy image before you are ready :).
- Added client authorization to work with Etherpad. Before it would get blocked because it doesn't have the required claim. As this is now fixed etherpad-proxy can also work with your new OAuth2 configuration and retrieve a token via client credentials flow.
# 2.2.7 # 2.2.7

View file

@ -3,9 +3,10 @@
# https://github.com/ether/etherpad-lite # https://github.com/ether/etherpad-lite
# #
# Author: muxator # Author: muxator
ARG BUILD_ENV=git
FROM node:alpine AS adminbuild FROM node:alpine AS adminbuild
RUN npm install -g pnpm@9.0.4 RUN npm install -g pnpm@latest
WORKDIR /opt/etherpad-lite WORKDIR /opt/etherpad-lite
COPY . . COPY . .
RUN pnpm install RUN pnpm install
@ -99,7 +100,7 @@ RUN mkdir -p "${EP_DIR}" && chown etherpad:etherpad "${EP_DIR}"
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=863199 # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=863199
RUN \ RUN \
mkdir -p /usr/share/man/man1 && \ mkdir -p /usr/share/man/man1 && \
npm install pnpm@9.0.4 -g && \ npm install pnpm@latest -g && \
apk update && apk upgrade && \ apk update && apk upgrade && \
apk add --no-cache \ apk add --no-cache \
ca-certificates \ ca-certificates \
@ -113,26 +114,49 @@ USER etherpad
WORKDIR "${EP_DIR}" WORKDIR "${EP_DIR}"
# etherpads version feature requires this. Only copy what is really needed # etherpads version feature requires this. Only copy what is really needed
COPY --chown=etherpad:etherpad ./.git/HEA[D] ./.git/HEAD
COPY --chown=etherpad:etherpad ./.git/ref[s] ./.git/refs
COPY --chown=etherpad:etherpad ${SETTINGS} ./settings.json COPY --chown=etherpad:etherpad ${SETTINGS} ./settings.json
COPY --chown=etherpad:etherpad ./var ./var COPY --chown=etherpad:etherpad ./var ./var
COPY --chown=etherpad:etherpad ./bin ./bin COPY --chown=etherpad:etherpad ./bin ./bin
COPY --chown=etherpad:etherpad ./pnpm-workspace.yaml ./package.json ./ COPY --chown=etherpad:etherpad ./pnpm-workspace.yaml ./package.json ./
FROM build AS development
FROM build AS build_git
ONBUILD COPY --chown=etherpad:etherpad ./.git/HEA[D] ./.git/HEAD
ONBUILD COPY --chown=etherpad:etherpad ./.git/ref[s] ./.git/refs
FROM build AS build_copy
FROM build_${BUILD_ENV} AS development
ARG ETHERPAD_PLUGINS=
ARG ETHERPAD_LOCAL_PLUGINS=
ARG ETHERPAD_LOCAL_PLUGINS_ENV=
ARG ETHERPAD_GITHUB_PLUGINS=
COPY --chown=etherpad:etherpad ./src/ ./src/ COPY --chown=etherpad:etherpad ./src/ ./src/
COPY --chown=etherpad:etherpad --from=adminbuild /opt/etherpad-lite/src/ templates/admin./src/templates/admin COPY --chown=etherpad:etherpad --from=adminbuild /opt/etherpad-lite/src/ templates/admin./src/templates/admin
COPY --chown=etherpad:etherpad --from=adminbuild /opt/etherpad-lite/src/static/oidc ./src/static/oidc COPY --chown=etherpad:etherpad --from=adminbuild /opt/etherpad-lite/src/static/oidc ./src/static/oidc
COPY --chown=etherpad:etherpad ./local_plugin[s] ./local_plugins/
RUN bash -c ./bin/installLocalPlugins.sh
RUN bin/installDeps.sh && \ RUN bin/installDeps.sh && \
if [ ! -z "${ETHERPAD_PLUGINS}" ] || [ ! -z "${ETHERPAD_LOCAL_PLUGINS}" ] || [ ! -z "${ETHERPAD_GITHUB_PLUGINS}" ]; then \ if [ ! -z "${ETHERPAD_PLUGINS}" ] || [ ! -z "${ETHERPAD_GITHUB_PLUGINS}" ]; then \
pnpm run plugins i ${ETHERPAD_PLUGINS} ${ETHERPAD_LOCAL_PLUGINS:+--path ${ETHERPAD_LOCAL_PLUGINS}} ${ETHERPAD_GITHUB_PLUGINS:+--github ${ETHERPAD_GITHUB_PLUGINS}}; \ pnpm run plugins i ${ETHERPAD_PLUGINS} ${ETHERPAD_GITHUB_PLUGINS:+--github ${ETHERPAD_GITHUB_PLUGINS}}; \
fi fi
FROM build AS production FROM build_${BUILD_ENV} AS production
ARG ETHERPAD_PLUGINS=
ARG ETHERPAD_LOCAL_PLUGINS=
ARG ETHERPAD_LOCAL_PLUGINS_ENV=
ARG ETHERPAD_GITHUB_PLUGINS=
ENV NODE_ENV=production ENV NODE_ENV=production
ENV ETHERPAD_PRODUCTION=true ENV ETHERPAD_PRODUCTION=true
@ -141,9 +165,13 @@ COPY --chown=etherpad:etherpad ./src ./src
COPY --chown=etherpad:etherpad --from=adminbuild /opt/etherpad-lite/src/templates/admin ./src/templates/admin COPY --chown=etherpad:etherpad --from=adminbuild /opt/etherpad-lite/src/templates/admin ./src/templates/admin
COPY --chown=etherpad:etherpad --from=adminbuild /opt/etherpad-lite/src/static/oidc ./src/static/oidc COPY --chown=etherpad:etherpad --from=adminbuild /opt/etherpad-lite/src/static/oidc ./src/static/oidc
RUN bin/installDeps.sh && rm -rf ~/.npm && rm -rf ~/.local && rm -rf ~/.cache && \ COPY --chown=etherpad:etherpad ./local_plugin[s] ./local_plugins/
if [ ! -z "${ETHERPAD_PLUGINS}" ] || [ ! -z "${ETHERPAD_LOCAL_PLUGINS}" ] || [ ! -z "${ETHERPAD_GITHUB_PLUGINS}" ]; then \
pnpm run plugins i ${ETHERPAD_PLUGINS} ${ETHERPAD_LOCAL_PLUGINS:+--path ${ETHERPAD_LOCAL_PLUGINS}} ${ETHERPAD_GITHUB_PLUGINS:+--github ${ETHERPAD_GITHUB_PLUGINS}}; \ RUN bash -c ./bin/installLocalPlugins.sh
RUN bin/installDeps.sh && \
if [ ! -z "${ETHERPAD_PLUGINS}" ] || [ ! -z "${ETHERPAD_GITHUB_PLUGINS}" ]; then \
pnpm run plugins i ${ETHERPAD_PLUGINS} ${ETHERPAD_GITHUB_PLUGINS:+--github ${ETHERPAD_GITHUB_PLUGINS}}; \
fi fi
# Copy the configuration file. # Copy the configuration file.

View file

@ -1,7 +1,7 @@
{ {
"name": "admin", "name": "admin",
"private": true, "private": true,
"version": "2.2.7", "version": "2.3.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@ -11,32 +11,32 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@radix-ui/react-switch": "^1.1.2" "@radix-ui/react-switch": "^1.1.3"
}, },
"devDependencies": { "devDependencies": {
"@radix-ui/react-dialog": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-toast": "^1.2.4", "@radix-ui/react-toast": "^1.2.6",
"@types/react": "^19.0.2", "@types/react": "^19.0.12",
"@types/react-dom": "^19.0.2", "@types/react-dom": "^19.0.4",
"@typescript-eslint/eslint-plugin": "^8.18.1", "@typescript-eslint/eslint-plugin": "^8.28.0",
"@typescript-eslint/parser": "^8.18.1", "@typescript-eslint/parser": "^8.28.0",
"@vitejs/plugin-react-swc": "^3.7.2", "@vitejs/plugin-react-swc": "^3.8.1",
"eslint": "^9.17.0", "eslint": "^9.23.0",
"eslint-plugin-react-hooks": "^5.1.0", "eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.16", "eslint-plugin-react-refresh": "^0.4.19",
"i18next": "^24.2.0", "i18next": "^24.2.3",
"i18next-browser-languagedetector": "^8.0.2", "i18next-browser-languagedetector": "^8.0.4",
"lucide-react": "^0.469.0", "lucide-react": "^0.487.0",
"react": "^19.0.0", "react": "^19.1.0",
"react-dom": "^19.0.0", "react-dom": "^19.1.0",
"react-hook-form": "^7.54.1", "react-hook-form": "^7.55.0",
"react-i18next": "^15.2.0", "react-i18next": "^15.4.1",
"react-router-dom": "^7.0.2", "react-router-dom": "^7.4.1",
"socket.io-client": "^4.8.1", "socket.io-client": "^4.8.1",
"typescript": "^5.7.2", "typescript": "^5.8.2",
"vite": "^6.0.5", "vite": "^6.2.5",
"vite-plugin-static-copy": "^2.2.0", "vite-plugin-static-copy": "^2.3.0",
"vite-plugin-svgr": "^4.3.0", "vite-plugin-svgr": "^4.3.0",
"zustand": "^5.0.2" "zustand": "^5.0.3"
} }
} }

51
bin/installLocalPlugins.sh Executable file
View file

@ -0,0 +1,51 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
trim() {
local var="$*"
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"
printf '%s' "$var"
}
# Move to the Etherpad base directory.
MY_DIR=$(cd "${0%/*}" && pwd -P) || exit 1
cd "${MY_DIR}/.." || exit 1
# Source constants and useful functions
. bin/functions.sh
PNPM_OPTIONS=
if [ ! -z "${NODE_ENV-}" ]; then
if [ "$NODE_ENV" == 'production' ]; then
PNPM_OPTIONS='--prod'
fi
fi
if [ ! -z "${ETHERPAD_LOCAL_PLUGINS_ENV-}" ]; then
if [ "$ETHERPAD_LOCAL_PLUGINS_ENV" == 'production' ]; then
PNPM_OPTIONS='--prod'
elif [ "$ETHERPAD_LOCAL_PLUGINS_ENV" == 'development' ]; then
PNPM_OPTIONS='-D'
fi
fi
if [ ! -z "${ETHERPAD_LOCAL_PLUGINS}" ]; then
readarray -d ' ' plugins <<< "${ETHERPAD_LOCAL_PLUGINS}"
for plugin in "${plugins[@]}"; do
plugin=$(trim "$plugin")
if [ -d "local_plugins/${plugin}" ]; then
echo "Installing plugin: '${plugin}'"
pnpm install -w ${PNPM_OPTIONS:-} "local_plugins/${plugin}/"
else
( echo "Error. Directory 'local_plugins/${plugin}' for local plugin " \
"'${plugin}' missing" >&2 )
exit 1
fi
done
else
echo 'No local plugings to install.'
fi

View file

@ -1,23 +1,23 @@
{ {
"name": "bin", "name": "bin",
"version": "2.2.7", "version": "2.3.0",
"description": "", "description": "",
"main": "checkAllPads.js", "main": "checkAllPads.js",
"directories": { "directories": {
"doc": "doc" "doc": "doc"
}, },
"dependencies": { "dependencies": {
"axios": "^1.7.9", "axios": "^1.8.4",
"ep_etherpad-lite": "workspace:../src", "ep_etherpad-lite": "workspace:../src",
"log4js": "^6.9.1", "log4js": "^6.9.1",
"semver": "^7.6.3", "semver": "^7.7.1",
"tsx": "^4.19.2", "tsx": "^4.19.3",
"ueberdb2": "^5.0.6" "ueberdb2": "^5.0.6"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.10.2", "@types/node": "^22.13.14",
"@types/semver": "^7.5.8", "@types/semver": "^7.7.0",
"typescript": "^5.7.2" "typescript": "^5.8.2"
}, },
"scripts": { "scripts": {
"makeDocs": "node --import tsx make_docs.ts", "makeDocs": "node --import tsx make_docs.ts",

View file

@ -1,6 +1,6 @@
{ {
"devDependencies": { "devDependencies": {
"vitepress": "^1.5.0" "vitepress": "^1.6.3"
}, },
"scripts": { "scripts": {
"docs:dev": "vitepress dev", "docs:dev": "vitepress dev",

3
local_plugins/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
# ignore everything
*
!.gitignore

View file

@ -50,6 +50,6 @@
"type": "git", "type": "git",
"url": "https://github.com/ether/etherpad-lite.git" "url": "https://github.com/ether/etherpad-lite.git"
}, },
"version": "2.2.7", "version": "2.3.0",
"license": "Apache-2.0" "license": "Apache-2.0"
} }

5985
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -4,3 +4,7 @@ packages:
- bin - bin
- doc - doc
- ui - ui
onlyBuiltDependencies:
- '@scarf/scarf'
- '@swc/core'
- esbuild

View file

@ -11,6 +11,7 @@
"Predatorix", "Predatorix",
"SamTV", "SamTV",
"Sebastian Wallroth", "Sebastian Wallroth",
"Ssgl",
"Thargon", "Thargon",
"Tim.krieger", "Tim.krieger",
"Wikinaut", "Wikinaut",
@ -85,6 +86,7 @@
"pad.settings.fontType": "Schriftart:", "pad.settings.fontType": "Schriftart:",
"pad.settings.fontType.normal": "Normal", "pad.settings.fontType.normal": "Normal",
"pad.settings.language": "Sprache:", "pad.settings.language": "Sprache:",
"pad.settings.deletePad": "Pad löschen",
"pad.delete.confirm": "Möchtest du dieses Pad wirklich löschen?", "pad.delete.confirm": "Möchtest du dieses Pad wirklich löschen?",
"pad.settings.about": "Über", "pad.settings.about": "Über",
"pad.settings.poweredBy": "Betrieben von", "pad.settings.poweredBy": "Betrieben von",

View file

@ -14,10 +14,12 @@
"admin_plugins": "Διαχειριστής πρόσθετων", "admin_plugins": "Διαχειριστής πρόσθετων",
"admin_plugins.available": "Διαθέσιμα πρόσθετα", "admin_plugins.available": "Διαθέσιμα πρόσθετα",
"admin_plugins.available_not-found": "Δεν βρέθηκαν πρόσθετα.", "admin_plugins.available_not-found": "Δεν βρέθηκαν πρόσθετα.",
"admin_plugins.available_fetching": "Ανακτάται...",
"admin_plugins.available_install.value": "Εγκατάσταση", "admin_plugins.available_install.value": "Εγκατάσταση",
"admin_plugins.available_search.placeholder": "Αναζητήστε πρόσθετα για εγκατάσταση", "admin_plugins.available_search.placeholder": "Αναζητήστε πρόσθετα για εγκατάσταση",
"admin_plugins.description": "Περιγραφή", "admin_plugins.description": "Περιγραφή",
"admin_plugins.installed": "Εγκατεστημένα πρόσθετα", "admin_plugins.installed": "Εγκατεστημένα πρόσθετα",
"admin_plugins.installed_fetching": "Ανάκτηση εγκατεστημένων προσθηκών…",
"admin_plugins.installed_nothing": "Δεν έχετε εγκαταστήσει πρόσθετα ακόμη.", "admin_plugins.installed_nothing": "Δεν έχετε εγκαταστήσει πρόσθετα ακόμη.",
"admin_plugins.installed_uninstall.value": "Απεγκατάσταση", "admin_plugins.installed_uninstall.value": "Απεγκατάσταση",
"admin_plugins.last-update": "Τελευταία ενημέρωση", "admin_plugins.last-update": "Τελευταία ενημέρωση",
@ -75,6 +77,8 @@
"pad.settings.fontType": "Τύπος γραμματοσειράς:", "pad.settings.fontType": "Τύπος γραμματοσειράς:",
"pad.settings.fontType.normal": "Κανονική", "pad.settings.fontType.normal": "Κανονική",
"pad.settings.language": "Γλώσσα:", "pad.settings.language": "Γλώσσα:",
"pad.settings.deletePad": "Διαγραφή Pad",
"pad.delete.confirm": "Θέλετε πραγματικά να διαγράψετε αυτό το pad;",
"pad.settings.about": "Σχετικά", "pad.settings.about": "Σχετικά",
"pad.settings.poweredBy": "Υποστηρίζεται από", "pad.settings.poweredBy": "Υποστηρίζεται από",
"pad.importExport.import_export": "Εισαγωγή/Εξαγωγή", "pad.importExport.import_export": "Εισαγωγή/Εξαγωγή",
@ -89,7 +93,7 @@
"pad.importExport.exportopen": "ODF (Open Document Format)", "pad.importExport.exportopen": "ODF (Open Document Format)",
"pad.importExport.abiword.innerHTML": "Μπορείτε να εισάγετε απλό κείμενο ή HTML. Για προηγμένες δυνατότητες εισαγωγής παρακαλούμε <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">εγκαταστήστε το AbiWord ή το LibreOffice</a>.", "pad.importExport.abiword.innerHTML": "Μπορείτε να εισάγετε απλό κείμενο ή HTML. Για προηγμένες δυνατότητες εισαγωγής παρακαλούμε <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">εγκαταστήστε το AbiWord ή το LibreOffice</a>.",
"pad.modals.connected": "Συνδεμένοι.", "pad.modals.connected": "Συνδεμένοι.",
"pad.modals.reconnecting": "Επανασύνδεση στο pad σας...", "pad.modals.reconnecting": "Επανασύνδεση στο pad σας",
"pad.modals.forcereconnect": "Επιβολή επανασύνδεσης", "pad.modals.forcereconnect": "Επιβολή επανασύνδεσης",
"pad.modals.reconnecttimer": "Προσπάθεια επανασύνδεσης σε", "pad.modals.reconnecttimer": "Προσπάθεια επανασύνδεσης σε",
"pad.modals.cancel": "Ακύρωση", "pad.modals.cancel": "Ακύρωση",
@ -111,7 +115,9 @@
"pad.modals.corruptPad.cause": "Αυτό μπορεί να οφείλεται σε ένα λάθος στη ρύθμιση του διακομιστή ή κάποια άλλη απρόβλεπτη συμπεριφορά. Παρακαλώ επικοινωνήστε με τον διαχειριστή της υπηρεσίας.", "pad.modals.corruptPad.cause": "Αυτό μπορεί να οφείλεται σε ένα λάθος στη ρύθμιση του διακομιστή ή κάποια άλλη απρόβλεπτη συμπεριφορά. Παρακαλώ επικοινωνήστε με τον διαχειριστή της υπηρεσίας.",
"pad.modals.deleted": "Διεγράφη.", "pad.modals.deleted": "Διεγράφη.",
"pad.modals.deleted.explanation": "Αυτό το pad έχει καταργηθεί.", "pad.modals.deleted.explanation": "Αυτό το pad έχει καταργηθεί.",
"pad.modals.rateLimited.explanation": "Στείλατε πάρα πολλά μηνύματα σε αυτό το pad, επομένως σας αποσύνδεσε.",
"pad.modals.rejected.explanation": "Ο διακομιστής απέρριψε ένα μήνυμα που στάλθηκε από το πρόγραμμα περιήγησής σας.", "pad.modals.rejected.explanation": "Ο διακομιστής απέρριψε ένα μήνυμα που στάλθηκε από το πρόγραμμα περιήγησής σας.",
"pad.modals.rejected.cause": "Ο διακομιστής μπορεί να έχει ενημερωθεί ενώ προβάλλατε το pad ή ίσως υπάρχει σφάλμα στο Etherpad. Δοκιμάστε να φορτώσετε ξανά τη σελίδα.",
"pad.modals.disconnected": "Είστε αποσυνδεδεμένοι.", "pad.modals.disconnected": "Είστε αποσυνδεδεμένοι.",
"pad.modals.disconnected.explanation": "Χάθηκε η σύνδεση με τον διακομιστή", "pad.modals.disconnected.explanation": "Χάθηκε η σύνδεση με τον διακομιστή",
"pad.modals.disconnected.cause": "Ο διακομιστής μπορεί να μην είναι διαθέσιμος. Παρακαλούμε ειδοποιήστε τον διαχειριστή της υπηρεσίας εάν εξακολουθεί να συμβαίνει αυτό.", "pad.modals.disconnected.cause": "Ο διακομιστής μπορεί να μην είναι διαθέσιμος. Παρακαλούμε ειδοποιήστε τον διαχειριστή της υπηρεσίας εάν εξακολουθεί να συμβαίνει αυτό.",
@ -124,6 +130,7 @@
"pad.chat.loadmessages": "Φόρτωση περισσότερων μηνυμάτων", "pad.chat.loadmessages": "Φόρτωση περισσότερων μηνυμάτων",
"pad.chat.stick.title": "Κρατήστε τη συνομιλία στην οθόνη", "pad.chat.stick.title": "Κρατήστε τη συνομιλία στην οθόνη",
"pad.chat.writeMessage.placeholder": "Γράψτε το μήνυμα σας εδώ", "pad.chat.writeMessage.placeholder": "Γράψτε το μήνυμα σας εδώ",
"timeslider.followContents": "Ακολουθήστε τις ενημερώσεις περιεχομένου του pad",
"timeslider.pageTitle": "{{appTitle}} Χρονοδιάγραμμα", "timeslider.pageTitle": "{{appTitle}} Χρονοδιάγραμμα",
"timeslider.toolbar.returnbutton": "Επιστροφή στο pad", "timeslider.toolbar.returnbutton": "Επιστροφή στο pad",
"timeslider.toolbar.authors": "Συντάκτες:", "timeslider.toolbar.authors": "Συντάκτες:",

View file

@ -87,6 +87,8 @@
"pad.settings.fontType": "Fonttityyppi:", "pad.settings.fontType": "Fonttityyppi:",
"pad.settings.fontType.normal": "normaali", "pad.settings.fontType.normal": "normaali",
"pad.settings.language": "Kieli:", "pad.settings.language": "Kieli:",
"pad.settings.deletePad": "Poista muistio",
"pad.delete.confirm": "Haluatko todella poistaa tämän muistion?",
"pad.settings.about": "Tietoja", "pad.settings.about": "Tietoja",
"pad.settings.poweredBy": "Palvelun mahdollistaa", "pad.settings.poweredBy": "Palvelun mahdollistaa",
"pad.importExport.import_export": "Tuonti/vienti", "pad.importExport.import_export": "Tuonti/vienti",

View file

@ -72,6 +72,8 @@
"pad.settings.fontType": "Typo de litteras:", "pad.settings.fontType": "Typo de litteras:",
"pad.settings.fontType.normal": "Normal", "pad.settings.fontType.normal": "Normal",
"pad.settings.language": "Lingua:", "pad.settings.language": "Lingua:",
"pad.settings.deletePad": "Deler pad",
"pad.delete.confirm": "Es tu secur de voler deler iste pad?",
"pad.settings.about": "A proposito", "pad.settings.about": "A proposito",
"pad.settings.poweredBy": "Actionate per", "pad.settings.poweredBy": "Actionate per",
"pad.importExport.import_export": "Importar/Exportar", "pad.importExport.import_export": "Importar/Exportar",

View file

@ -63,7 +63,7 @@
"pad.colorpicker.save": "Išsaugoti", "pad.colorpicker.save": "Išsaugoti",
"pad.colorpicker.cancel": "Atšaukti", "pad.colorpicker.cancel": "Atšaukti",
"pad.loading": "Įkraunama...", "pad.loading": "Įkraunama...",
"pad.noCookie": "Slapuko nepavyko rasti. Prašome leisti slapukus interneto naršyklėje!", "pad.noCookie": "Slapuko rasti nepavyko. Prašome leisti slapukus savo naršyklėje! Jūsų sesija ir nustatymai nebus išsaugoti tarp apsilankymų. Taip gali būti dėl to, kad kai kuriose naršyklėse Etherpad yra įtrauktas į iFrame. Įsitikinkite, kad Etherpad yra tame pačiame padomenyje / domene kaip ir pirminis iFrame.",
"pad.permissionDenied": "Jūs neturite leidimo patekti į šį bloknotą", "pad.permissionDenied": "Jūs neturite leidimo patekti į šį bloknotą",
"pad.settings.padSettings": "Bloknoto nustatymai", "pad.settings.padSettings": "Bloknoto nustatymai",
"pad.settings.myView": "Mano Vaizdas", "pad.settings.myView": "Mano Vaizdas",
@ -75,6 +75,8 @@
"pad.settings.fontType": "Šrifto tipas:", "pad.settings.fontType": "Šrifto tipas:",
"pad.settings.fontType.normal": "Normalus", "pad.settings.fontType.normal": "Normalus",
"pad.settings.language": "Kalba:", "pad.settings.language": "Kalba:",
"pad.settings.deletePad": "Ištrinti bloką",
"pad.delete.confirm": "Ar tikrai norite ištrinti šį bloką?",
"pad.settings.about": "Apie", "pad.settings.about": "Apie",
"pad.settings.poweredBy": "Palaiko", "pad.settings.poweredBy": "Palaiko",
"pad.importExport.import_export": "Importuoti/Eksportuoti", "pad.importExport.import_export": "Importuoti/Eksportuoti",

View file

@ -9,6 +9,8 @@
"ਪ੍ਰਚਾਰਕ" "ਪ੍ਰਚਾਰਕ"
] ]
}, },
"admin_plugins.available_fetching": "ਲਿਆਉਣਾ ਪਿਆਂ...",
"admin_plugins.available_install.value": "ਜੜੋ",
"admin_plugins.description": "ਵੇਰਵਾ", "admin_plugins.description": "ਵੇਰਵਾ",
"admin_plugins.last-update": "ਆਖਰੀ ਵਾਰ ਨਵਿਆਈਆ ਗਿਆ", "admin_plugins.last-update": "ਆਖਰੀ ਵਾਰ ਨਵਿਆਈਆ ਗਿਆ",
"admin_plugins.name": "ਨਾਂ", "admin_plugins.name": "ਨਾਂ",
@ -48,7 +50,7 @@
"pad.settings.colorcheck": "ਲੇਖਕੀ ਰੰਗ", "pad.settings.colorcheck": "ਲੇਖਕੀ ਰੰਗ",
"pad.settings.linenocheck": "ਲਕੀਰ ਨੰਬਰ", "pad.settings.linenocheck": "ਲਕੀਰ ਨੰਬਰ",
"pad.settings.rtlcheck": "ਸਮੱਗਰੀ ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਪੜ੍ਹਨੀ ਹੈ?", "pad.settings.rtlcheck": "ਸਮੱਗਰੀ ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਪੜ੍ਹਨੀ ਹੈ?",
"pad.settings.fontType": "ਫੋਂਟ ਕਿਸਮ:", "pad.settings.fontType": "ਅੱਖਰ ਦੀ ਕਿਸਮ:",
"pad.settings.fontType.normal": "ਆਮ", "pad.settings.fontType.normal": "ਆਮ",
"pad.settings.language": "ਭਾਸ਼ਾ:", "pad.settings.language": "ਭਾਸ਼ਾ:",
"pad.settings.about": "ਬਾਬਤ", "pad.settings.about": "ਬਾਬਤ",
@ -126,13 +128,13 @@
"pad.userlist.entername": "ਆਪਣਾ ਨਾਂ ਦਿਉ", "pad.userlist.entername": "ਆਪਣਾ ਨਾਂ ਦਿਉ",
"pad.userlist.unnamed": "ਬੇਨਾਮ", "pad.userlist.unnamed": "ਬੇਨਾਮ",
"pad.editbar.clearcolors": "ਪੂਰੇ ਦਸਾਤਵੇਜ਼ ਉੱਤੇ ਪਰਮਾਣਕਿਤਾ ਰੰਗ ਸਾਫ਼ ਕਰਨੇ ਹਨ?", "pad.editbar.clearcolors": "ਪੂਰੇ ਦਸਾਤਵੇਜ਼ ਉੱਤੇ ਪਰਮਾਣਕਿਤਾ ਰੰਗ ਸਾਫ਼ ਕਰਨੇ ਹਨ?",
"pad.impexp.importbutton": "ਹੁਣੇ ਇੰਪੋਰਟ ਕਰੋ", "pad.impexp.importbutton": "ਹੁਣੇ ਦਰਾਮਦ ਕਰੋ",
"pad.impexp.importing": "...ਇੰਪੋਰਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ", "pad.impexp.importing": "...ਇੰਪੋਰਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ",
"pad.impexp.confirmimport": "ਕੋਈ ਫ਼ਾਈਲ ਦਰਾਮਦ ਕਾਰਨ ਨਾਲ਼ ਪੈਡ ਦੀ ਮੌਜੂਦਾ ਲਿਖਤ ਉੱਤੇ ਲਿਖਿਆ ਜਾਵੇਗਾ। ਕੀ ਤੁਸੀਂ ਸੱਚੀਂ ਇਹ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?", "pad.impexp.confirmimport": "ਕੋਈ ਫ਼ਾਈਲ ਦਰਾਮਦ ਕਾਰਨ ਨਾਲ਼ ਪੈਡ ਦੀ ਮੌਜੂਦਾ ਲਿਖਤ ਉੱਤੇ ਲਿਖਿਆ ਜਾਵੇਗਾ। ਕੀ ਤੁਸੀਂ ਸੱਚੀਂ ਇਹ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?",
"pad.impexp.convertFailed": "ਅਸੀਂ ਇਸ ਫ਼ਾਈਲ ਦੀ ਦਰਾਮਦ ਨਹੀਂ ਕਰ ਸਕੇ। ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਕੋਈ ਵੱਖਰੀ ਦਸਤਾਵੇਜ਼ੀ ਰੂਪ-ਰੇਖਾ ਵਰਤੋ ਜਾਂ ਹੱਥੀਂ ਨਕਲ-ਚੇਪੀ ਕਰੋ।", "pad.impexp.convertFailed": "ਅਸੀਂ ਇਸ ਫ਼ਾਈਲ ਦੀ ਦਰਾਮਦ ਨਹੀਂ ਕਰ ਸਕੇ। ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਕੋਈ ਵੱਖਰੀ ਦਸਤਾਵੇਜ਼ੀ ਰੂਪ-ਰੇਖਾ ਵਰਤੋ ਜਾਂ ਹੱਥੀਂ ਨਕਲ-ਚੇਪੀ ਕਰੋ।",
"pad.impexp.padHasData": "ਅਸੀ ਇਸ ਫਾਈਲ ਨੂੰ ਆਯਾਤ ਨਹੀੰ ਕਰ ਸਕੇ ਕਿਉੰਕਿ ਇਸ ਪੈਡ ਉੱਤੇ ਪਹਿਲਾੰ ਹੀ ਤਬਦੀਲੀਆੰ ਕੀਤੀਆੰ ਜਾ ਚੁਕੀਆੰ ਹਨ, ਕਿਰਪਾ ਕਰਕੇ ਨਵੇੰ ਪੈਡ ਵਿਚ ਆਯਾਤ ਕਰੋ", "pad.impexp.padHasData": "ਅਸੀ ਇਸ ਫਾਈਲ ਨੂੰ ਦਰਾਮਦ ਨਹੀੰ ਕਰ ਸਕੇ ਕਿਉੰਕਿ ਇਸ ਕਾਗਜ਼ ਉੱਤੇ ਪਹਿਲਾਂ ਹੀ ਤਬਦੀਲੀਆਂ ਕੀਤੀਆਂ ਜਾ ਚੁਕੀਆਂ ਹਨ, ਕਿਰਪਾ ਕਰਕੇ ਨਵੇਂ ਕਾਗਜ਼ ਵਿਚ ਦਰਾਮਦ ਕਰੋ",
"pad.impexp.uploadFailed": "ਅੱਪਲੋਡ ਲਈ ਫੇਲ੍ਹ ਹੈ, ਫੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ ਜੀ।", "pad.impexp.uploadFailed": "ਅੱਪਲੋਡ ਲਈ ਫੇਲ੍ਹ ਹੈ, ਫੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ ਜੀ।",
"pad.impexp.importfailed": "ਇੰਪੋਰਟ ਫੇਲ੍ਹ ਹੈ", "pad.impexp.importfailed": "ਦਰਾਮਦ ਨਾਕਾਮ",
"pad.impexp.copypaste": "ਕਾਪੀ ਕਰੋ ਚੇਪੋ ਜੀ", "pad.impexp.copypaste": "ਕਾਪੀ ਕਰੋ ਚੇਪੋ ਜੀ",
"pad.impexp.exportdisabled": "{{type}} ਫਾਰਮੈਟ ਵਜੋਂ ਬਰਾਮਦ ਕਰਨਾ ਬੰਦ ਹੈ। ਵੇਰਵੇ ਵਾਸਤੇ ਆਪਣੇ ਸਿਸਟਮ ਦੇ ਪਰਬੰਧਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।" "pad.impexp.exportdisabled": "{{type}} ਫਾਰਮੈਟ ਵਜੋਂ ਬਰਾਮਦ ਕਰਨਾ ਬੰਦ ਹੈ। ਵੇਰਵੇ ਵਾਸਤੇ ਆਪਣੇ ਸਿਸਟਮ ਦੇ ਪਰਬੰਧਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"
} }

View file

@ -71,6 +71,8 @@
"pad.settings.rtlcheck": "Ël contnù, dev-lo esse lesù da drita a snistra?", "pad.settings.rtlcheck": "Ël contnù, dev-lo esse lesù da drita a snistra?",
"pad.settings.fontType": "Sòrt ëd caràter:", "pad.settings.fontType": "Sòrt ëd caràter:",
"pad.settings.language": "Lenga:", "pad.settings.language": "Lenga:",
"pad.settings.deletePad": "Eliminé ël blochet",
"pad.delete.confirm": "Veul-lo për da bon eliminé cost blochet?",
"pad.settings.about": "A propòsit", "pad.settings.about": "A propòsit",
"pad.settings.poweredBy": "Potensià da", "pad.settings.poweredBy": "Potensià da",
"pad.importExport.import_export": "Amporté/Esporté", "pad.importExport.import_export": "Amporté/Esporté",

View file

@ -20,9 +20,10 @@
*/ */
import {MapArrayType} from "../types/MapType"; import {MapArrayType} from "../types/MapType";
import { jwtDecode } from "jwt-decode";
const api = require('../db/API'); const api = require('../db/API');
const padManager = require('../db/PadManager'); const padManager = require('../db/PadManager');
const settings = require('../utils/Settings');
import createHTTPError from 'http-errors'; import createHTTPError from 'http-errors';
import {Http2ServerRequest} from "node:http2"; import {Http2ServerRequest} from "node:http2";
import {publicKeyExported} from "../security/OAuth2Provider"; import {publicKeyExported} from "../security/OAuth2Provider";
@ -182,8 +183,17 @@ exports.handle = async function (apiVersion: string, functionName: string, field
throw new createHTTPError.Unauthorized('no or wrong API Key'); throw new createHTTPError.Unauthorized('no or wrong API Key');
} }
try { try {
await jwtVerify(req.headers.authorization!.replace("Bearer ", ""), publicKeyExported!, {algorithms: ['RS256'], const clientIds: string[] = settings.sso.clients?.map((client: {client_id: string}) => client.client_id);
const jwtToCheck = req.headers.authorization.replace("Bearer ", "")
const payload = jwtDecode(jwtToCheck)
// client_credentials
if (clientIds.includes(<string>payload.sub)) {
await jwtVerify(jwtToCheck, publicKeyExported!, {algorithms: ['RS256']})
} else {
// authorization_code
await jwtVerify(jwtToCheck, publicKeyExported!, {algorithms: ['RS256'],
requiredClaims: ["admin"]}) requiredClaims: ["admin"]})
}
} catch (e) { } catch (e) {
throw new createHTTPError.Unauthorized('no or wrong OAuth token'); throw new createHTTPError.Unauthorized('no or wrong OAuth token');
} }

View file

@ -49,8 +49,20 @@ exports.userCanModify = (padId: string, req: SocketClientRequest) => {
// Exported so that tests can set this to 0 to avoid unnecessary test slowness. // Exported so that tests can set this to 0 to avoid unnecessary test slowness.
exports.authnFailureDelayMs = 1000; exports.authnFailureDelayMs = 1000;
const staticResources = [
/^\/padbootstrap-[a-zA-Z0-9]+\.min\.js$/,
/^\/manifest.json$/
]
const checkAccess = async (req:any, res:any, next: Function) => { const checkAccess = async (req:any, res:any, next: Function) => {
const requireAdmin = req.path.toLowerCase().startsWith('/admin-auth'); const requireAdmin = req.path.toLowerCase().startsWith('/admin-auth');
for (const staticResource of staticResources) {
if (req.path.match(staticResource)) {
console.log(`Loading [${staticResource}] ${req.path}`);
return next()
}
}
// /////////////////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////////////////
// Step 1: Check the preAuthorize hook for early permit/deny (permit is only allowed for non-admin // Step 1: Check the preAuthorize hook for early permit/deny (permit is only allowed for non-admin

View file

@ -32,57 +32,58 @@
"dependencies": { "dependencies": {
"@etherpad/express-session": "^1.18.4", "@etherpad/express-session": "^1.18.4",
"async": "^3.2.6", "async": "^3.2.6",
"axios": "^1.7.9", "axios": "^1.8.4",
"cookie-parser": "^1.4.7", "cookie-parser": "^1.4.7",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"cross-spawn": "^7.0.6", "cross-spawn": "^7.0.6",
"ejs": "^3.1.10", "ejs": "^3.1.10",
"esbuild": "^0.24.1", "esbuild": "^0.25.2",
"express": "4.21.2", "express": "4.21.2",
"express-rate-limit": "^7.5.0", "express-rate-limit": "^7.5.0",
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"find-root": "1.1.0", "find-root": "1.1.0",
"formidable": "^3.5.2", "formidable": "^3.5.2",
"http-errors": "^2.0.0", "http-errors": "^2.0.0",
"jose": "^5.9.6", "jose": "^5.10.0",
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"jsdom": "^25.0.1", "jsdom": "^26.0.0",
"jsonminify": "0.4.2", "jsonminify": "0.4.2",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"languages4translatewiki": "0.1.3", "languages4translatewiki": "0.1.3",
"live-plugin-manager": "^1.0.0", "live-plugin-manager": "^1.0.0",
"lodash.clonedeep": "4.5.0", "lodash.clonedeep": "4.5.0",
"log4js": "^6.9.1", "log4js": "^6.9.1",
"lru-cache": "^11.0.2", "lru-cache": "^11.1.0",
"measured-core": "^2.0.0", "measured-core": "^2.0.0",
"mime-types": "^2.1.35", "mime-types": "^3.0.1",
"oidc-provider": "^8.6.0", "oidc-provider": "^8.8.1",
"openapi-backend": "^5.11.1", "openapi-backend": "^5.11.1",
"proxy-addr": "^2.0.7", "proxy-addr": "^2.0.7",
"rate-limiter-flexible": "^5.0.4", "rate-limiter-flexible": "^6.2.1",
"rehype": "^13.0.2", "rehype": "^13.0.2",
"rehype-minify-whitespace": "^6.0.2", "rehype-minify-whitespace": "^6.0.2",
"resolve": "1.22.10", "resolve": "1.22.10",
"rusty-store-kv": "^1.3.1", "rusty-store-kv": "^1.3.1",
"security": "1.0.0", "security": "1.0.0",
"semver": "^7.6.3", "semver": "^7.7.1",
"socket.io": "^4.8.1", "socket.io": "^4.8.1",
"socket.io-client": "^4.8.1", "socket.io-client": "^4.8.1",
"superagent": "10.1.1", "superagent": "10.2.0",
"swagger-ui-express": "^5.0.1", "swagger-ui-express": "^5.0.1",
"jwt-decode": "^4.0.0",
"tinycon": "0.6.8", "tinycon": "0.6.8",
"tsx": "4.19.2", "tsx": "4.19.3",
"ueberdb2": "^5.0.6", "ueberdb2": "^5.0.6",
"underscore": "1.13.7", "underscore": "1.13.7",
"unorm": "1.6.0", "unorm": "1.6.0",
"wtfnode": "^0.9.4" "wtfnode": "^0.10.0"
}, },
"bin": { "bin": {
"etherpad-healthcheck": "../bin/etherpad-healthcheck", "etherpad-healthcheck": "../bin/etherpad-healthcheck",
"etherpad-lite": "node/server.ts" "etherpad-lite": "node/server.ts"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.49.1", "@playwright/test": "^1.51.1",
"@types/async": "^3.2.24", "@types/async": "^3.2.24",
"@types/express": "^4.17.21", "@types/express": "^4.17.21",
"@types/formidable": "^3.4.5", "@types/formidable": "^3.4.5",
@ -90,31 +91,31 @@
"@types/jquery": "^3.5.32", "@types/jquery": "^3.5.32",
"@types/js-cookie": "^3.0.6", "@types/js-cookie": "^3.0.6",
"@types/jsdom": "^21.1.7", "@types/jsdom": "^21.1.7",
"@types/jsonwebtoken": "^9.0.7", "@types/jsonwebtoken": "^9.0.9",
"@types/mime-types": "^2.1.4", "@types/mime-types": "^2.1.4",
"@types/mocha": "^10.0.9", "@types/mocha": "^10.0.9",
"@types/node": "^22.10.2", "@types/node": "^22.13.14",
"@types/oidc-provider": "^8.5.2", "@types/oidc-provider": "^8.8.1",
"@types/semver": "^7.5.8", "@types/semver": "^7.7.0",
"@types/sinon": "^17.0.3", "@types/sinon": "^17.0.3",
"@types/supertest": "^6.0.2", "@types/supertest": "^6.0.2",
"@types/swagger-ui-express": "^4.1.7", "@types/swagger-ui-express": "^4.1.8",
"@types/underscore": "^1.13.0", "@types/underscore": "^1.13.0",
"@types/whatwg-mimetype": "^3.0.2", "@types/whatwg-mimetype": "^3.0.2",
"chokidar": "^4.0.3", "chokidar": "^4.0.3",
"eslint": "^9.17.0", "eslint": "^9.23.0",
"eslint-config-etherpad": "^4.0.4", "eslint-config-etherpad": "^4.0.4",
"etherpad-cli-client": "^3.0.2", "etherpad-cli-client": "^3.0.2",
"mocha": "^11.0.1", "mocha": "^11.1.0",
"mocha-froth": "^0.2.10", "mocha-froth": "^0.2.10",
"nodeify": "^1.0.1", "nodeify": "^1.0.1",
"openapi-schema-validation": "^0.4.2", "openapi-schema-validation": "^0.4.2",
"set-cookie-parser": "^2.7.1", "set-cookie-parser": "^2.7.1",
"sinon": "^19.0.2", "sinon": "^20.0.0",
"split-grid": "^1.0.11", "split-grid": "^1.0.11",
"supertest": "^7.0.0", "supertest": "^7.1.0",
"typescript": "^5.7.2", "typescript": "^5.8.2",
"vitest": "^2.1.8" "vitest": "^3.1.1"
}, },
"engines": { "engines": {
"node": ">=18.18.2", "node": ">=18.18.2",
@ -141,6 +142,6 @@
"debug:socketio": "cross-env DEBUG=socket.io* node --require tsx/cjs node/server.ts", "debug:socketio": "cross-env DEBUG=socket.io* node --require tsx/cjs node/server.ts",
"test:vitest": "vitest" "test:vitest": "vitest"
}, },
"version": "2.2.7", "version": "2.3.0",
"license": "Apache-2.0" "license": "Apache-2.0"
} }

View file

@ -186,7 +186,7 @@ const paduserlist = (() => {
const tr = input.closest('tr'); const tr = input.closest('tr');
if (tr.length > 0) { if (tr.length > 0) {
const index = tr.parent().children().index(tr); const index = tr.parent().children().index(tr);
if (index >= 0) { if (index >= 0 && rowsPresent.length > index) {
const userId = rowsPresent[index].data.id; const userId = rowsPresent[index].data.id;
rowManagerMakeNameEditor($(this), userId); rowManagerMakeNameEditor($(this), userId);
} }

View file

@ -24,7 +24,7 @@ const connect = (etherpadBaseUrl, namespace = '/', options = {}) => {
let socketOptions = { let socketOptions = {
path: socketioUrl.pathname, path: socketioUrl.pathname,
upgrade: true, upgrade: true,
transports: ['websocket'], transports: ['polling', 'websocket'],
}; };
socketOptions = Object.assign(options, socketOptions); socketOptions = Object.assign(options, socketOptions);

View file

@ -11,7 +11,7 @@
}, },
"devDependencies": { "devDependencies": {
"ep_etherpad-lite": "workspace:../src", "ep_etherpad-lite": "workspace:../src",
"typescript": "^5.7.2", "typescript": "^5.8.2",
"vite": "^6.0.5" "vite": "^6.2.5"
} }
} }