Merge branch 'hotfix/v1.1.3' into develop

# Conflicts:
#	common/ASC.Core.Common/Context/Impl/UserManager.cs
#	common/ASC.Core.Common/Core/ITenantService.cs
#	common/ASC.Core.Common/Data/DbTenantService.cs
#	common/ASC.Data.Storage/StorageHandler.cs
#	common/ASC.FederatedLogin/ASC.FederatedLogin.csproj
#	config/appsettings.json
#	config/nlog.config
#	migrations/mysql/SaaS/CoreDbContext/CoreDbContextModelSnapshot.cs
#	migrations/mysql/Standalone/MigrationContext/20230914152735_CoreDbContext_Upgrade2.Designer.cs
#	migrations/mysql/Standalone/MigrationContext/20230914152735_CoreDbContext_Upgrade2.cs
#	packages/client/src/pages/Confirm/sub-components/createUser.js
#	packages/client/src/pages/PortalSettings/categories/developer-tools/JavascriptSDK/index.js
#	packages/common/components/MoreLoginModal/index.tsx
#	packages/login/src/client/components/sub-components/LoginForm.tsx
#	products/ASC.Files/Core/HttpHandlers/ChunkedUploaderHandler.cs
#	products/ASC.Files/Core/Services/DocumentService/Configuration.cs
#	products/ASC.People/Server/Api/ThirdpartyController.cs
#	products/ASC.People/Server/GlobalUsings.cs
#	web/ASC.Web.Api/Core/CspSettingsHelper.cs
#	web/ASC.Web.Core/Users/UserManagerWrapper.cs
#	yarn.lock
This commit is contained in:
pavelbannov 2023-09-25 10:53:06 +03:00
commit b14d6c8ef0
149 changed files with 9147 additions and 890 deletions

View File

@ -3,57 +3,58 @@ name: Build packages
on:
push:
branches:
- release/*
- develop
- hotfix/*
- release/*
- develop
- hotfix/*
paths:
- build/install/deb**
- build/install/rpm**
- build/install/common**
- build/install/deb**
- build/install/rpm**
- build/install/common**
workflow_dispatch:
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
env:
BRANCH_NAME: $(echo ${GITHUB_REF#refs/heads/})
PRODUCT_LOW: $(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]' )
PRODUCT: "${{ github.event.repository.name }}"
BUILD_NUMBER: "${{ github.run_number }}"
env:
PRODUCT: ${{ github.event.repository.name }}
PRODUCT_LOW: echo ${{ github.event.repository.name }} | tr '[:upper:]' '[:lower:]'
PRODUCT_VERSION: echo ${{ github.ref }} | grep -oP '\d+\.\d+\.\d+' || echo '1.1.3'
BUILD_NUMBER: ${{ github.run_number }}
BRANCH_NAME: echo ${GITHUB_REF#refs/heads/}
PACKAGE_DIRECTORY: "/home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/build/install"
jobs:
build_deb:
name: DEB packages
build:
name: Build Packages
runs-on: ubuntu-20.04
permissions:
contents: write
strategy:
matrix:
packageType: [deb, rpm]
steps:
# To avoid mistake "System.IO.IOException: No space left on device"
- name: Free Disk Space
uses: jlumbroso/free-disk-space@main
with:
tool-cache: true
android: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- name: Import GPG
run: |
sudo rm -rf /usr/local/lib/android /opt/ghc
sudo docker image prune --all --force
- name: Import GPG
uses: crazy-max/ghaction-import-gpg@v5
id: gpg_step
with:
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PRIVATE_KEY_PASS }}
- name: Get files from repository
uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Prepare build
id: get_vars
run: |
wget -O - https://dl.yarnpkg.com/debian/pubkey.gpg | \
sudo gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/yarnkey.gpg --import
@ -69,103 +70,43 @@ jobs:
sudo gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/nodesource.gpg --import
sudo chmod 644 /usr/share/keyrings/nodesource.gpg
sudo apt-get -y update
sudo apt install -y dotnet-sdk-7.0 yarn nodejs dh-make rename dpkg-sig lintian
sudo apt install -y dotnet-sdk-7.0 yarn nodejs rename
sudo npm install -g json
echo "BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_OUTPUT
echo "VERSION=$(echo "${{ github.ref }}" | grep -oP '\d+\.\d+\.\d+' || echo "1.1.0")" >> $GITHUB_OUTPUT
- name: Build
shell: bash
if [[ "${{ matrix.packageType }}" == "rpm" ]]; then
sudo apt install -y python3-rpm python3-pip
sudo pip install rpmlint
else
sudo apt install -y dpkg-sig lintian dh-make
fi
- name: Build DEB Packages
if: matrix.packageType == 'deb'
run: |
cd build/install/deb/
rename -f -v "s/product([^\/]*)$/${{ env.PRODUCT_LOW }}\$1/g" debian/* ../common/* ../common/logrotate/*
find ../ -type f -exec sed -i "s/{{product}}/${{ env.PRODUCT_LOW }}/g" {} ';'
sed -i "s/{{package_header_tag_version}}/${{ steps.get_vars.outputs.VERSION }}.$BUILD_NUMBER/g" \
debian/changelog debian/control
cd build/install/deb/
rename -f -v "s/product([^\/]*)$/$(${{ env.PRODUCT_LOW }})\$1/g" debian/* ../common/* ../common/logrotate/*
find ../ -type f -exec sed -i "s/{{product}}/$(${{ env.PRODUCT_LOW }})/g" {} ';'
sed -i "s/{{package_header_tag_version}}/$(${{ env.PRODUCT_VERSION }}).${{ env.BUILD_NUMBER }}/g" debian/changelog debian/control
dpkg-buildpackage -uc -k${{ steps.gpg_step.outputs.fingerprint }}
- name: Upload to Nexus
run: |
for file in /home/runner/work/${{ env.PRODUCT }}/${{ env.PRODUCT }}/build/install/*.deb; do
echo $file
curl --verbose --user ${{ secrets.REPO_LOGIN }}:${{ secrets.REPO_PASS }} -H "Content-Type: multipart/form-data" \
--data-binary "@$file" ${{ secrets.REPO_URL_4TESTING_DEB }}
done
- name: Lint
run: |
lintian --suppress-tags=mismatched-override --profile debian /home/runner/work/${{ env.PRODUCT }}/${{ env.PRODUCT }}/build/install/*.deb \
| tee -a file
if grep -qE '^(W:|E:)' file; then echo \
"::warning Noticedeb=lintian::$(cat file | awk '/^W:/ { ws += 1 } /^E:/ { es += 1 } END { print "Warnings:", ws, "Errors:", es }')"; fi
build_rpm:
name: RPM packages
runs-on: ubuntu-20.04
permissions:
contents: write
steps:
- name: Free Disk Space
uses: jlumbroso/free-disk-space@main
with:
tool-cache: true
android: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- name: Import GPG
uses: crazy-max/ghaction-import-gpg@v5
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PRIVATE_KEY_PASS }}
- name: Get files from repository
uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Prepare build
id: get_vars
run: |
wget -O - https://dl.yarnpkg.com/debian/pubkey.gpg | sudo gpg --no-default-keyring --keyring \
gnupg-ring:/usr/share/keyrings/yarnkey.gpg --import
sudo chmod 644 /usr/share/keyrings/yarnkey.gpg
echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian/ stable main" | \
sudo tee /etc/apt/sources.list.d/yarn.list
wget https://packages.microsoft.com/config/$(lsb_release -is | \
tr [:upper:] [:lower:])/$(lsb_release -rs)/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | \
sudo tee /etc/apt/sources.list.d/nodesource.list
wget -O - https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | \
sudo gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/nodesource.gpg --import
sudo chmod 644 /usr/share/keyrings/nodesource.gpg
sudo apt-get -y update
sudo apt install -y dotnet-sdk-7.0 yarn nodejs dh-make rename python3-pip python3-rpm
sudo npm install -g json
sudo pip install rpmlint
echo "BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_OUTPUT
echo "VERSION=$(echo "${ GITHUB_REF##*/ }" | grep -oP '\d+\.\d+\.\d+' || echo "1.1.0")" >> $GITHUB_OUTPUT
- name: Build
- name: Build RPM Packages
if: matrix.packageType == 'rpm'
run: |
cd build/install/rpm/SPECS
mv ./SOURCES/product.rpmlintrc ./SOURCES/${{ env.PRODUCT_LOW }}.rpmlintrc
wget https://github.com/ONLYOFFICE/${{ env.PRODUCT }}/archive/${{ env.BRANCH_NAME }}.tar.gz \
-O ./SOURCES/${{ env.PRODUCT }}-$(echo ${{ env.BRANCH_NAME }} | tr '/' '-').tar.gz
mv ./SOURCES/product.rpmlintrc ./SOURCES/$(${{ env.PRODUCT_LOW }}).rpmlintrc
wget https://github.com/ONLYOFFICE/${{ env.PRODUCT }}/archive/$(${{ env.BRANCH_NAME }}).tar.gz \
-O ./SOURCES/${{ env.PRODUCT }}-$(${{ env.BRANCH_NAME }} | tr '/' '-').tar.gz
wget https://github.com/ONLYOFFICE/document-templates/archive/main/community-server.tar.gz \
-O ./SOURCES/document-templates-main-community-server.tar.gz
-O ./SOURCES/document-templates-main-community-server.tar.gz
wget https://github.com/ONLYOFFICE/dictionaries/archive/master.tar.gz \
-O ./SOURCES/dictionaries-master.tar.gz
-O ./SOURCES/dictionaries-master.tar.gz
sed -i -e '/BuildRequires/d' product.spec
rpmbuild -D "packager Ascensio System SIA <support@onlyoffice.com>" -D "GIT_BRANCH $(echo ${{ env.BRANCH_NAME }} \
| tr '/' '-')" -D "_topdir $(pwd)" -D "version ${{ steps.get_vars.outputs.VERSION }}" \
-D "release ${{ env.BUILD_NUMBER }}" -ba product.spec
rpmbuild -D "packager Ascensio System SIA <support@onlyoffice.com>" \
-D "GIT_BRANCH $(${{ env.BRANCH_NAME }}| tr '/' '-')" -D "_topdir $(pwd)" \
-D "version $(${{ env.PRODUCT_VERSION }})" \
-D "release ${{ env.BUILD_NUMBER }}" -ba product.spec
- name: Sign
- name: Sign RPM Packages
if: matrix.packageType == 'rpm'
run: |
cat << EOF >> $HOME/.rpmmacros
%_signature gpg
@ -175,21 +116,42 @@ jobs:
EOF
gpg --export --armor --output onlyoffice-gpgkey.pub
rpm --import onlyoffice-gpgkey.pub
rpm --addsign /home/runner/work/${{ env.PRODUCT }}/${{ env.PRODUCT }}/build/install/rpm/SPECS/RPMS/noarch/*.rpm
- name: Upload
rpm --addsign ${{ env.PACKAGE_DIRECTORY }}/rpm/SPECS/RPMS/noarch/*.rpm
- name: Upload DEB Packages
if: matrix.packageType == 'deb'
run: |
for file in /home/runner/work/${{ env.PRODUCT }}/${{ env.PRODUCT }}/build/install/rpm/SPECS/RPMS/noarch/*.rpm; do
curl --verbose --user ${{ secrets.REPO_LOGIN }}:${{ secrets.REPO_PASS }} \
--upload-file "$file" ${{ secrets.REPO_URL_4TESTING_RPM }}
for deb_package in ${{ env.PACKAGE_DIRECTORY }}/*.deb; do
echo $deb_package
curl --verbose \
--user ${{ secrets.REPO_LOGIN }}:${{ secrets.REPO_PASS }} \
-H "Content-Type: multipart/form-data" \
--data-binary "@$deb_package" ${{ secrets.REPO_URL_4TESTING_DEB }}
done
- name: Rpmlint
run: |
for package in /home/runner/work/${{ env.PRODUCT }}/${{ env.PRODUCT }}/build/install/rpm/SPECS/RPMS/noarch/*.rpm
do rpmlint --ignore-unused-rpmlintrc --rpmlintrc \
/home/runner/work/${{ env.PRODUCT }}/${{ env.PRODUCT }}/build/install/rpm/SPECS/SOURCES/${{ env.PRODUCT_LOW }}.rpmlintrc $package \
| tee -a file2
- name: Upload RPM Packages
if: matrix.packageType == 'rpm'
run: |
for rpm_package in ${{ env.PACKAGE_DIRECTORY }}/rpm/SPECS/RPMS/noarch/*.rpm; do
curl --verbose \
--user ${{ secrets.REPO_LOGIN }}:${{ secrets.REPO_PASS }} \
--upload-file "$rpm_package" ${{ secrets.REPO_URL_4TESTING_RPM }}
done
if grep -qE '^(W:|E:)' file2; then echo \
"::warning NoticeRpm=rpmLint::$(cat file2 | awk '/W:/ { ws += 1 } /E:/ { es += 1 } END { print "Warnings:", ws, "Errors:", es }')" ; fi
- name: Checking the DEB package for errors
if: matrix.packageType == 'deb'
run: |
lintian --profile debian ${{ env.PACKAGE_DIRECTORY }}/*.deb | tee -a LINTIAN
if grep -qE '^(W:|E:)' LINTIAN; then
echo "::warning Noticedeb=lintian::$(cat LINTIAN | awk '/^W:/ { ws += 1 } /^E:/ { es += 1 } END { print "Warnings:", ws, "Errors:", es }')"
fi
- name: Checking the RPM package for errors
if: matrix.packageType == 'rpm'
run: |
for rpm_package in ${{ env.PACKAGE_DIRECTORY }}/rpm/SPECS/RPMS/noarch/*.rpm; do
rpmlint --ignore-unused-rpmlintrc --rpmlintrc ${{ env.PACKAGE_DIRECTORY }}/rpm/SPECS/SOURCES/$(${{ env.PRODUCT_LOW }}).rpmlintrc $rpm_package | tee -a RPM_LINT
done
if grep -qE '(W:|E:)' RPM_LINT; then
echo "::warning Noticerpm=rpmlint::$(cat RPM_LINT | awk '/W:/ { ws += 1 } /E:/ { es += 1 } END { print "Warnings:", ws, "Errors:", es }')"
fi

View File

@ -25,13 +25,12 @@ if [ "$UPDATE" = "true" ] && [ "$DOCUMENT_SERVER_INSTALLED" = "true" ]; then
debconf-get-selections | grep ^${ds_pkg_installed_name} | sed s/${ds_pkg_installed_name}/${ds_pkg_name}/g | debconf-set-selections
apt-get remove -yq ${ds_pkg_installed_name}
DEBIAN_FRONTEND=noninteractive apt-get purge -yq ${ds_pkg_installed_name}
apt-get install -yq ${ds_pkg_name}
RECONFIGURE_PRODUCT="true"
else
systemctl list-units --type=service | grep -q openresty && systemctl stop openresty
apt-get install -y --only-upgrade ${ds_pkg_name};
fi
fi
@ -61,8 +60,6 @@ if [ "$DOCUMENT_SERVER_INSTALLED" = "false" ]; then
echo ${package_sysname}-documentserver $DS_COMMON_NAME/jwt-enabled select ${DS_JWT_ENABLED} | sudo debconf-set-selections
echo ${package_sysname}-documentserver $DS_COMMON_NAME/jwt-secret select ${DS_JWT_SECRET} | sudo debconf-set-selections
echo ${package_sysname}-documentserver $DS_COMMON_NAME/jwt-header select ${DS_JWT_HEADER} | sudo debconf-set-selections
systemctl list-units --type=service | grep -q openresty && systemctl stop openresty
if [ "$INSTALLATION_TYPE" = "COMMUNITY" ]; then
apt-get install -yq ${package_sysname}-documentserver
@ -83,7 +80,7 @@ elif [ "$UPDATE" = "true" ] && [ "$PRODUCT_INSTALLED" = "true" ]; then
AVAILABLE_VERSIONS=$(apt show ${product} 2>/dev/null | grep -E '^Version:' | awk '{print $2}')
if [[ "$AVAILABLE_VERSIONS" != *"$CURRENT_VERSION"* ]]; then
apt-get install -o DPkg::options::="--force-confnew" -y --only-upgrade ${product} elasticsearch=${ELASTIC_VERSION}
elif [ $RECONFIGURE_PRODUCT = "true" ]; then
elif [ "${RECONFIGURE_PRODUCT}" = "true" ]; then
DEBIAN_FRONTEND=noninteractive dpkg-reconfigure ${product}
fi
fi

View File

@ -32,7 +32,7 @@ fi
locale-gen en_US.UTF-8
# add elasticsearch repo
ELASTIC_VERSION="7.10.0"
ELASTIC_VERSION="7.16.3"
ELASTIC_DIST=$(echo $ELASTIC_VERSION | awk '{ print int($1) }')
curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/elastic-${ELASTIC_DIST}.x.gpg --import
echo "deb [signed-by=/usr/share/keyrings/elastic-${ELASTIC_DIST}.x.gpg] https://artifacts.elastic.co/packages/${ELASTIC_DIST}.x/apt stable main" | tee /etc/apt/sources.list.d/elastic-${ELASTIC_DIST}.x.list
@ -99,13 +99,19 @@ if [ "$DIST" = "ubuntu" ]; then
chmod 644 /usr/share/keyrings/redis.gpg
fi
#add nginx repo
curl -s http://nginx.org/keys/nginx_signing.key | gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/nginx.gpg --import
echo "deb [signed-by=/usr/share/keyrings/nginx.gpg] http://nginx.org/packages/$DIST/ $DISTRIB_CODENAME nginx" | tee /etc/apt/sources.list.d/nginx.list
chmod 644 /usr/share/keyrings/nginx.gpg
#Temporary fix for missing nginx repository for debian bookworm
[ "$DISTRIB_CODENAME" = "bookworm" ] && sed -i "s/$DISTRIB_CODENAME/buster/g" /etc/apt/sources.list.d/nginx.list
#add openresty repo
curl -fsSL https://openresty.org/package/pubkey.gpg | gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/openresty.gpg --import
echo "deb [signed-by=/usr/share/keyrings/openresty.gpg] http://openresty.org/package/$DIST $DISTRIB_CODENAME $([ "$DIST" = "ubuntu" ] && echo "main" || echo "openresty" )" | tee /etc/apt/sources.list.d/openresty.list
chmod 644 /usr/share/keyrings/openresty.gpg
#Temporary fix for missing openresty repository for debian bookworm
[ "$DISTRIB_CODENAME" = "bookworm" ] && sed -i "s/$DISTRIB_CODENAME/bullseye/g" /etc/apt/sources.list.d/openresty.list
systemctl list-units --type=service | grep -q nginx && systemctl stop nginx && systemctl disable nginx
# setup msttcorefonts
echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections
@ -124,7 +130,6 @@ apt-get install -o DPkg::options::="--force-confnew" -yq \
postgresql \
redis-server \
rabbitmq-server \
openresty \
ffmpeg
if ! dpkg -l | grep -q "elasticsearch"; then

View File

@ -544,6 +544,7 @@ while [ "$1" != "" ]; do
done
root_checking () {
PID=$$
if [ ! $( id -u ) -eq 0 ]; then
echo "To perform this action you must be logged in with root rights"
exit 1;
@ -719,7 +720,7 @@ install_service () {
fi
if ! command_exists $COMMAND_NAME; then
echo "command $COMMAND_NAME not found"
echo "Command $COMMAND_NAME not found"
exit 1;
fi
}
@ -876,9 +877,9 @@ docker_login () {
}
create_network () {
EXIST=$(docker network ls | awk '{print $2;}' | { grep -x ${NETWORK_NAME} || true; });
NETWORT_EXIST=$(docker network ls | awk '{print $2;}' | { grep -x ${NETWORK_NAME} || true; });
if [[ -z ${EXIST} ]]; then
if [[ -z ${NETWORT_EXIST} ]]; then
docker network create --driver bridge ${NETWORK_NAME}
fi
}
@ -903,7 +904,11 @@ read_continue_installation () {
domain_check () {
if ! command_exists dig; then
install_service dig dnsutils
if command_exists apt-get; then
install_service dig dnsutils
elif command_exists yum; then
install_service dig bind-utils
fi
fi
if ! command_exists ping; then
@ -966,14 +971,9 @@ establish_conn() {
echo "OK"
}
get_container_env_parameter () {
local CONTAINER_NAME=$1;
local PARAMETER_NAME=$2;
if [[ -z ${CONTAINER_NAME} ]]; then
echo "Empty container name"
exit 1;
fi
get_env_parameter () {
local PARAMETER_NAME=$1;
local CONTAINER_NAME=$2;
if [[ -z ${PARAMETER_NAME} ]]; then
echo "Empty parameter name"
@ -981,15 +981,15 @@ get_container_env_parameter () {
fi
if command_exists docker ; then
CONTAINER_EXIST=$(docker ps -aqf "name=$CONTAINER_NAME");
[ -n "$CONTAINER_NAME" ] && CONTAINER_EXIST=$(docker ps -aqf "name=$CONTAINER_NAME");
if [[ -n ${CONTAINER_EXIST} ]]; then
VALUE=$(docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' ${CONTAINER_NAME} | grep "${PARAMETER_NAME}=" | sed 's/^.*=//');
fi
fi
if [ -z $VALUE ] && [ -f $BASE_DIR/.env ]; then
VALUE=$(awk -F= "/${PARAMETER_NAME}/ {print \$2}" $BASE_DIR/.env | tr -d '\r')
fi
if [ -z ${VALUE} ] && [ -f ${BASE_DIR}/.env ]; then
VALUE=$(awk -F= "/${PARAMETER_NAME}/ {print \$2}" ${BASE_DIR}/.env | tr -d '\r')
fi
echo ${VALUE//\"}
@ -1059,11 +1059,16 @@ get_available_version () {
LATEST_TAG=$(echo $TAG_LIST | tr ',' '\n' | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n | awk '/./{line=$0} END{print line}');
echo "$LATEST_TAG" | sed "s/\"//g"
if [ ! -z "${LATEST_TAG}" ]; then
echo "${LATEST_TAG}" | sed "s/\"//g"
else
echo "Unable to retrieve tag from ${1} repository" >&2
kill -s TERM $PID
fi
}
set_url_external () {
DOCUMENT_SERVER_URL_EXTERNAL=${DOCUMENT_SERVER_URL_EXTERNAL:-$(get_container_env_parameter "${CONTAINER_NAME}" "DOCUMENT_SERVER_URL_EXTERNAL")};
set_docs_url_external () {
DOCUMENT_SERVER_URL_EXTERNAL=${DOCUMENT_SERVER_URL_EXTERNAL:-$(get_env_parameter "DOCUMENT_SERVER_URL_EXTERNAL" "${CONTAINER_NAME}")};
if [[ ! -z ${DOCUMENT_SERVER_URL_EXTERNAL} ]] && [[ $DOCUMENT_SERVER_URL_EXTERNAL =~ ^(https?://)?([^:/]+)(:([0-9]+))?(/.*)?$ ]]; then
[[ -z ${BASH_REMATCH[1]} ]] && DOCUMENT_SERVER_URL_EXTERNAL="http://$DOCUMENT_SERVER_URL_EXTERNAL"
@ -1073,133 +1078,59 @@ set_url_external () {
}
set_jwt_secret () {
CURRENT_JWT_SECRET="";
if [[ -z ${DOCUMENT_SERVER_JWT_SECRET} ]]; then
CURRENT_JWT_SECRET=$(get_container_env_parameter "${PACKAGE_SYSNAME}-document-server" "JWT_SECRET");
if [[ -n ${CURRENT_JWT_SECRET} ]]; then
DOCUMENT_SERVER_JWT_SECRET="$CURRENT_JWT_SECRET";
fi
fi
if [[ -z ${DOCUMENT_SERVER_JWT_SECRET} ]]; then
CURRENT_JWT_SECRET=$(get_container_env_parameter "${CONTAINER_NAME}" "DOCUMENT_SERVER_JWT_SECRET");
if [[ -n ${CURRENT_JWT_SECRET} ]]; then
DOCUMENT_SERVER_JWT_SECRET="$CURRENT_JWT_SECRET";
fi
fi
if [[ -z ${DOCUMENT_SERVER_JWT_SECRET} ]] && [ -f $BASE_DIR/.env ]; then
DOCUMENT_SERVER_JWT_SECRET=$(sed -n "/.*DOCUMENT_SERVER_JWT_SECRET=/s///p" $BASE_DIR/.env)
fi
if [[ -z ${DOCUMENT_SERVER_JWT_SECRET} ]]; then
DOCUMENT_SERVER_JWT_SECRET=$(get_random_str 32);
fi
DOCUMENT_SERVER_JWT_SECRET="${DOCUMENT_SERVER_JWT_SECRET:-$(get_env_parameter "JWT_SECRET" "${PACKAGE_SYSNAME}-document-server")}"
DOCUMENT_SERVER_JWT_SECRET="${DOCUMENT_SERVER_JWT_SECRET:-$(get_env_parameter "DOCUMENT_SERVER_JWT_SECRET" "${CONTAINER_NAME}")}"
DOCUMENT_SERVER_JWT_SECRET="${DOCUMENT_SERVER_JWT_SECRET:-$(get_random_str 32)}"
}
set_jwt_header () {
CURRENT_JWT_HEADER="";
if [[ -z ${DOCUMENT_SERVER_JWT_HEADER} ]]; then
CURRENT_JWT_HEADER=$(get_container_env_parameter "${PACKAGE_SYSNAME}-document-server" "JWT_HEADER");
if [[ -n ${CURRENT_JWT_HEADER} ]]; then
DOCUMENT_SERVER_JWT_HEADER="$CURRENT_JWT_HEADER";
fi
fi
if [[ -z ${DOCUMENT_SERVER_JWT_HEADER} ]]; then
CURRENT_JWT_HEADER=$(get_container_env_parameter "${CONTAINER_NAME}" "DOCUMENT_SERVER_JWT_HEADER");
if [[ -n ${CURRENT_JWT_HEADER} ]]; then
DOCUMENT_SERVER_JWT_HEADER="$CURRENT_JWT_HEADER";
fi
fi
if [[ -z ${DOCUMENT_SERVER_JWT_HEADER} ]] && [ -f $BASE_DIR/.env ]; then
DOCUMENT_SERVER_JWT_HEADER=$(sed -n "/.*DOCUMENT_SERVER_JWT_HEADER=/s///p" $BASE_DIR/.env)
fi
if [[ -z ${DOCUMENT_SERVER_JWT_HEADER} ]]; then
DOCUMENT_SERVER_JWT_HEADER="AuthorizationJwt"
fi
DOCUMENT_SERVER_JWT_HEADER="${DOCUMENT_SERVER_JWT_HEADER:-$(get_env_parameter "JWT_HEADER" "${PACKAGE_SYSNAME}-document-server")}"
DOCUMENT_SERVER_JWT_HEADER="${DOCUMENT_SERVER_JWT_HEADER:-$(get_env_parameter "DOCUMENT_SERVER_JWT_HEADER" "${CONTAINER_NAME}")}"
DOCUMENT_SERVER_JWT_HEADER="${DOCUMENT_SERVER_JWT_HEADER:-"AuthorizationJwt"}"
}
set_core_machinekey () {
if [[ -z ${APP_CORE_MACHINEKEY} ]]; then
CURRENT_CORE_MACHINEKEY=$(get_container_env_parameter "${CONTAINER_NAME}" "APP_CORE_MACHINEKEY");
if [[ -n ${CURRENT_CORE_MACHINEKEY} ]]; then
APP_CORE_MACHINEKEY="$CURRENT_CORE_MACHINEKEY";
fi
fi
if [[ -z ${APP_CORE_MACHINEKEY} ]] && [[ "$UPDATE" != "true" ]]; then
APP_CORE_MACHINEKEY=$(get_random_str 12);
fi
APP_CORE_MACHINEKEY="${APP_CORE_MACHINEKEY:-$(get_env_parameter "APP_CORE_MACHINEKEY" "${CONTAINER_NAME}")}"
[[ "$UPDATE" != "true" ]] && APP_CORE_MACHINEKEY="${APP_CORE_MACHINEKEY:-$(get_random_str 12))}"
}
set_mysql_params () {
if [[ -z ${MYSQL_PASSWORD} ]]; then
MYSQL_PASSWORD=$(get_container_env_parameter "${CONTAINER_NAME}" "MYSQL_PASSWORD");
MYSQL_PASSWORD="${MYSQL_PASSWORD:-$(get_env_parameter "MYSQL_PASSWORD" "${CONTAINER_NAME}")}"
MYSQL_PASSWORD="${MYSQL_PASSWORD:-$(get_random_str 20)}"
if [[ -z ${MYSQL_PASSWORD} ]]; then
MYSQL_PASSWORD=$(get_random_str 20);
fi
fi
if [[ -z ${MYSQL_ROOT_PASSWORD} ]]; then
MYSQL_ROOT_PASSWORD=$(get_container_env_parameter "${CONTAINER_NAME}" "MYSQL_ROOT_PASSWORD");
MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-$(get_env_parameter "MYSQL_ROOT_PASSWORD" "${CONTAINER_NAME}")}"
MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-$(get_random_str 20)}"
if [[ -z ${MYSQL_ROOT_PASSWORD} ]]; then
MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD:-$(get_random_str 20)};
fi
fi
if [[ -z ${MYSQL_DATABASE} ]]; then
MYSQL_DATABASE=$(get_container_env_parameter "${CONTAINER_NAME}" "MYSQL_DATABASE");
fi
if [[ -z ${MYSQL_USER} ]]; then
MYSQL_USER=$(get_container_env_parameter "${CONTAINER_NAME}" "MYSQL_USER");
fi
if [[ -z ${MYSQL_HOST} ]]; then
MYSQL_HOST=$(get_container_env_parameter "${CONTAINER_NAME}" "MYSQL_HOST");
fi
if [[ -z ${MYSQL_PORT} ]]; then
MYSQL_PORT=$(get_container_env_parameter "${CONTAINER_NAME}" "MYSQL_PORT");
fi
MYSQL_DATABASE="${MYSQL_DATABASE:-$(get_env_parameter "MYSQL_DATABASE" "${CONTAINER_NAME}")}"
MYSQL_USER="${MYSQL_USER:-$(get_env_parameter "MYSQL_USER" "${CONTAINER_NAME}")}"
MYSQL_HOST="${MYSQL_HOST:-$(get_env_parameter "MYSQL_HOST" "${CONTAINER_NAME}")}"
MYSQL_PORT="${MYSQL_PORT:-$(get_env_parameter "MYSQL_PORT" "${CONTAINER_NAME}")}"
}
set_docspace_params() {
ENV_EXTENSION=${ENV_EXTENSION:-$(get_container_env_parameter "${CONTAINER_NAME}" "ENV_EXTENSION")};
APP_CORE_BASE_DOMAIN=${APP_CORE_BASE_DOMAIN:-$(get_container_env_parameter "${CONTAINER_NAME}" "APP_CORE_BASE_DOMAIN")};
APP_URL_PORTAL=${APP_URL_PORTAL:-$(get_container_env_parameter "${CONTAINER_NAME}" "APP_URL_PORTAL")};
EXTERNAL_PORT=${EXTERNAL_PORT:-$(get_container_env_parameter "${CONTAINER_NAME}" "EXTERNAL_PORT")};
ENV_EXTENSION=${ENV_EXTENSION:-$(get_env_parameter "ENV_EXTENSION" "${CONTAINER_NAME}")};
APP_CORE_BASE_DOMAIN=${APP_CORE_BASE_DOMAIN:-$(get_env_parameter "APP_CORE_BASE_DOMAIN" "${CONTAINER_NAME}")};
APP_URL_PORTAL=${APP_URL_PORTAL:-$(get_env_parameter "APP_URL_PORTAL" "${CONTAINER_NAME}")};
EXTERNAL_PORT=${EXTERNAL_PORT:-$(get_env_parameter "EXTERNAL_PORT" "${CONTAINER_NAME}")};
ELK_SHEME=${ELK_SHEME:-$(get_container_env_parameter "${CONTAINER_NAME}" "ELK_SHEME")};
ELK_HOST=${ELK_HOST:-$(get_container_env_parameter "${CONTAINER_NAME}" "ELK_HOST")};
ELK_PORT=${ELK_PORT:-$(get_container_env_parameter "${CONTAINER_NAME}" "ELK_PORT")};
ELK_SHEME=${ELK_SHEME:-$(get_env_parameter "ELK_SHEME" "${CONTAINER_NAME}")};
ELK_HOST=${ELK_HOST:-$(get_env_parameter "ELK_HOST" "${CONTAINER_NAME}")};
ELK_PORT=${ELK_PORT:-$(get_env_parameter "ELK_PORT" "${CONTAINER_NAME}")};
REDIS_HOST=${REDIS_HOST:-$(get_container_env_parameter "${CONTAINER_NAME}" "REDIS_HOST")};
REDIS_PORT=${REDIS_PORT:-$(get_container_env_parameter "${CONTAINER_NAME}" "REDIS_PORT")};
REDIS_USER_NAME=${REDIS_USER_NAME:-$(get_container_env_parameter "${CONTAINER_NAME}" "REDIS_USER_NAME")};
REDIS_PASSWORD=${REDIS_PASSWORD:-$(get_container_env_parameter "${CONTAINER_NAME}" "REDIS_PASSWORD")};
REDIS_HOST=${REDIS_HOST:-$(get_env_parameter "REDIS_HOST" "${CONTAINER_NAME}")};
REDIS_PORT=${REDIS_PORT:-$(get_env_parameter "REDIS_PORT" "${CONTAINER_NAME}")};
REDIS_USER_NAME=${REDIS_USER_NAME:-$(get_env_parameter "REDIS_USER_NAME" "${CONTAINER_NAME}")};
REDIS_PASSWORD=${REDIS_PASSWORD:-$(get_env_parameter "REDIS_PASSWORD" "${CONTAINER_NAME}")};
RABBIT_HOST=${RABBIT_HOST:-$(get_container_env_parameter "${CONTAINER_NAME}" "RABBIT_HOST")};
RABBIT_PORT=${RABBIT_PORT:-$(get_container_env_parameter "${CONTAINER_NAME}" "RABBIT_PORT")};
RABBIT_USER_NAME=${RABBIT_USER_NAME:-$(get_container_env_parameter "${CONTAINER_NAME}" "RABBIT_USER_NAME")};
RABBIT_PASSWORD=${RABBIT_PASSWORD:-$(get_container_env_parameter "${CONTAINER_NAME}" "RABBIT_PASSWORD")};
RABBIT_VIRTUAL_HOST=${RABBIT_VIRTUAL_HOST:-$(get_container_env_parameter "${CONTAINER_NAME}" "RABBIT_VIRTUAL_HOST")};
RABBIT_HOST=${RABBIT_HOST:-$(get_env_parameter "RABBIT_HOST" "${CONTAINER_NAME}")};
RABBIT_PORT=${RABBIT_PORT:-$(get_env_parameter "RABBIT_PORT" "${CONTAINER_NAME}")};
RABBIT_USER_NAME=${RABBIT_USER_NAME:-$(get_env_parameter "RABBIT_USER_NAME" "${CONTAINER_NAME}")};
RABBIT_PASSWORD=${RABBIT_PASSWORD:-$(get_env_parameter "RABBIT_PASSWORD" "${CONTAINER_NAME}")};
RABBIT_VIRTUAL_HOST=${RABBIT_VIRTUAL_HOST:-$(get_env_parameter "RABBIT_VIRTUAL_HOST" "${CONTAINER_NAME}")};
CERTIFICATE_PATH=${CERTIFICATE_PATH:-$(get_container_env_parameter "${CONTAINER_NAME}" "CERTIFICATE_PATH")};
CERTIFICATE_KEY_PATH=${CERTIFICATE_KEY_PATH:-$(get_container_env_parameter "${CONTAINER_NAME}" "CERTIFICATE_KEY_PATH")};
DHPARAM_PATH=${DHPARAM_PATH:-$(get_container_env_parameter "${CONTAINER_NAME}" "DHPARAM_PATH")};
CERTIFICATE_PATH=${CERTIFICATE_PATH:-$(get_env_parameter "CERTIFICATE_PATH")};
CERTIFICATE_KEY_PATH=${CERTIFICATE_KEY_PATH:-$(get_env_parameter "CERTIFICATE_KEY_PATH")};
DHPARAM_PATH=${DHPARAM_PATH:-$(get_env_parameter "DHPARAM_PATH")};
}
set_installation_type_data () {
@ -1226,10 +1157,14 @@ download_files () {
install_docker_compose
fi
# Fixes issues with variables when upgrading to v1.1.3
HOSTS=("ELK_HOST" "REDIS_HOST" "RABBIT_HOST" "MYSQL_HOST");
for HOST in "${HOSTS[@]}"; do [[ "${!HOST}" == *CONTAINER_PREFIX* || "${!HOST}" == *$PACKAGE_SYSNAME* ]] && export "$HOST="; done
[[ "${APP_URL_PORTAL}" == *${PACKAGE_SYSNAME}-proxy* ]] && APP_URL_PORTAL=""
svn export --force https://github.com/${PACKAGE_SYSNAME}/${PRODUCT}/branches/${GIT_BRANCH}/build/install/docker/ ${BASE_DIR}
echo -n "Downloading configuration files to the ${BASE_DIR} directory..."
svn export --force https://github.com/${PACKAGE_SYSNAME}/${PRODUCT}/branches/${GIT_BRANCH}/build/install/docker/ ${BASE_DIR} >/dev/null
echo "OK"
reconfigure STATUS ${STATUS}
reconfigure INSTALLATION_TYPE ${INSTALLATION_TYPE}
@ -1336,19 +1271,17 @@ install_product () {
reconfigure APP_URL_PORTAL "${APP_URL_PORTAL:-"http://${PACKAGE_SYSNAME}-router:8092"}"
reconfigure EXTERNAL_PORT ${EXTERNAL_PORT}
if [ ! -z "${CERTIFICATE_PATH}" ] && [ ! -z "${CERTIFICATE_KEY_PATH}" ]; then
bash $BASE_DIR/config/${PRODUCT}-ssl-setup -f "${CERTIFICATE_PATH}" "${CERTIFICATE_KEY_PATH}"
PROXY_YML="${BASE_DIR}/proxy-ssl.yml"
elif [ ! -z "${LETS_ENCRYPT_DOMAIN}" ] && [ ! -z "${LETS_ENCRYPT_MAIL}" ]; then
bash $BASE_DIR/config/${PRODUCT}-ssl-setup "${LETS_ENCRYPT_MAIL}" "${LETS_ENCRYPT_DOMAIN}"
PROXY_YML="${BASE_DIR}/proxy-ssl.yml"
fi
docker-compose -f $BASE_DIR/migration-runner.yml up -d
docker-compose -f $BASE_DIR/${PRODUCT}.yml up -d
docker-compose -f ${PROXY_YML} up -d
docker-compose -f $BASE_DIR/notify.yml up -d
docker-compose -f $BASE_DIR/healthchecks.yml up -d
if [ ! -z "${CERTIFICATE_PATH}" ] && [ ! -z "${CERTIFICATE_KEY_PATH}" ]; then
bash $BASE_DIR/config/${PRODUCT}-ssl-setup -f "${CERTIFICATE_PATH}" "${CERTIFICATE_KEY_PATH}"
elif [ ! -z "${LETS_ENCRYPT_DOMAIN}" ] && [ ! -z "${LETS_ENCRYPT_MAIL}" ]; then
bash $BASE_DIR/config/${PRODUCT}-ssl-setup "${LETS_ENCRYPT_MAIL}" "${LETS_ENCRYPT_DOMAIN}"
fi
}
make_swap () {
@ -1413,7 +1346,7 @@ start_installation () {
set_docspace_params
fi
set_url_external
set_docs_url_external
set_jwt_secret
set_jwt_header

View File

@ -99,7 +99,7 @@ if [ "$DOCUMENT_SERVER_INSTALLED" = "false" ]; then
su - postgres -s /bin/bash -c "psql -c \"CREATE USER ${DS_DB_USER} WITH password '${DS_DB_PWD}';\""
su - postgres -s /bin/bash -c "psql -c \"CREATE DATABASE ${DS_DB_NAME} OWNER ${DS_DB_USER};\""
fi
if [ "$INSTALLATION_TYPE" = "COMMUNITY" ]; then
${package_manager} -y install ${package_sysname}-documentserver
else
@ -155,7 +155,7 @@ if [ "$PRODUCT_INSTALLED" = "false" ]; then
-mysqld ${MYSQL_SERVER_DB_NAME} \
-mysqlu ${MYSQL_SERVER_USER} \
-mysqlp ${MYSQL_ROOT_PASS}
elif [[ $PRODUCT_CHECK_UPDATE -eq $UPDATE_AVAILABLE_CODE || $RECONFIGURE_PRODUCT = "true" ]]; then
elif [[ "${PRODUCT_CHECK_UPDATE}" -eq "${UPDATE_AVAILABLE_CODE}" || "${RECONFIGURE_PRODUCT}" = "true" ]]; then
ENVIRONMENT=$(grep -oP 'ENVIRONMENT=\K.*' /usr/lib/systemd/system/${product}-api.service)
CONNECTION_STRING=$(json -f /etc/${package_sysname}/${product}/appsettings.$ENVIRONMENT.json ConnectionStrings.default.connectionString)
${package_manager} -y update ${product}

View File

@ -59,18 +59,12 @@ curl -s https://packagecloud.io/install/repositories/rabbitmq/rabbitmq-server/sc
curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | os=centos dist=$REV bash
#add nodejs repo
if [ "$REV" != "8" ]; then
[ "$REV" = "7" ] && NODE_VERSION="16" || NODE_VERSION="18"
yum install -y https://rpm.nodesource.com/pub_${NODE_VERSION}.x/nodistro/repo/nodesource-release-nodistro-1.noarch.rpm
else
curl -sL https://rpm.nodesource.com/setup_18.x | bash - || true
rpm --import http://rpm.nodesource.com/pub/el/NODESOURCE-GPG-SIGNING-KEY-EL
fi
[ "$REV" = "8" ] && NODEJS_OPTION="--setopt=nodesource-nodejs.module_hotfixes=1"
[ "$REV" = "7" ] && NODE_VERSION="16" || NODE_VERSION="18"
yum install -y https://rpm.nodesource.com/pub_${NODE_VERSION}.x/nodistro/repo/nodesource-release-nodistro-1.noarch.rpm || true
#add dotnet repo
if [ $REV = "7" ] || [[ $DIST != "redhat" && $REV = "8" ]]; then
rpm -Uvh https://packages.microsoft.com/config/centos/$REV/packages-microsoft-prod.rpm || true
fi
[ $REV = "7" ] && rpm -Uvh https://packages.microsoft.com/config/centos/$REV/packages-microsoft-prod.rpm || true
#add mysql repo
[ "$REV" != "7" ] && dnf remove -y @mysql && dnf module -y reset mysql && dnf module -y disable mysql
@ -82,7 +76,7 @@ if ! rpm -q mysql-community-server; then
fi
#add elasticsearch repo
ELASTIC_VERSION="7.10.0"
ELASTIC_VERSION="7.16.3"
ELASTIC_DIST=$(echo $ELASTIC_VERSION | awk '{ print int($1) }')
rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
cat > /etc/yum.repos.d/elasticsearch.repo <<END
@ -96,18 +90,27 @@ autorefresh=1
type=rpm-md
END
# add nginx repo
cat > /etc/yum.repos.d/nginx.repo <<END
[nginx-stable]
name=nginx stable repo
baseurl=https://nginx.org/packages/centos/$REV/\$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
END
rpm --import https://openresty.org/package/pubkey.gpg
OPENRESTY_REPO_FILE=$( [[ "$REV" -ge 9 ]] && echo "openresty2.repo" || echo "openresty.repo" )
curl -o /etc/yum.repos.d/openresty.repo "https://openresty.org/package/centos/${OPENRESTY_REPO_FILE}"
systemctl list-units --type=service | grep -q nginx && systemctl stop nginx && systemctl disable nginx
${package_manager} -y install epel-release \
python3 \
nodejs \
nodejs ${NODEJS_OPTION} \
dotnet-sdk-7.0 \
elasticsearch-${ELASTIC_VERSION} --enablerepo=elasticsearch \
mysql-server \
openresty \
postgresql \
postgresql-server \
rabbitmq-server$rabbitmq_version \
@ -124,4 +127,4 @@ postgresql-setup initdb || true
semanage permissive -a httpd_t
package_services="rabbitmq-server postgresql redis openresty mysqld"
package_services="rabbitmq-server postgresql redis mysqld"

View File

@ -11,8 +11,8 @@ PRODUCT_DIR="/var/www/${PRODUCT}"
LOG_DIR="/var/log/${PACKAGE_SYSNAME}/${PRODUCT}"
USER_CONF="$APP_DIR/appsettings.$ENVIRONMENT.json"
NGINX_CONF="/usr/local/openresty/nginx/conf/nginx.conf"
NGINX_DIR="/etc/nginx"
OPENRESTY_CONF="/usr/local/openresty/nginx/conf/nginx.conf"
OPENRESTY_DIR="/etc/openresty"
DB_HOST="localhost"
DB_PORT="3306"
@ -32,12 +32,13 @@ RABBITMQ_USER="guest"
RABBITMQ_PASSWORD="guest"
RABBITMQ_PORT="5672"
REDIS_HOST="localhost"
REDIS_HOST="127.0.0.1"
REDIS_PORT="6379"
JSON="json -I -f"
[ $(id -u) -ne 0 ] && { echo "Root privileges required"; exit 1; }
check_localhost() { [ "$1" = "localhost" ] || [ "$1" = "127.0.0.1" ] && return 1 || return 0; }
while [ "$1" != "" ]; do
case $1 in
@ -66,6 +67,7 @@ while [ "$1" != "" ]; do
-esh | --elastichost )
if [ "$2" != "" ]; then
ELK_HOST=$2
check_localhost "$ELK_HOST" && EXTERNAL_ELK_FLAG="true"
shift
fi
;;
@ -115,6 +117,7 @@ while [ "$1" != "" ]; do
-rdh | --redishost )
if [ "$2" != "" ]; then
REDIS_HOST=$2
check_localhost "$REDIS_HOST" && EXTERNAL_REDIS_FLAG="true"
shift
fi
;;
@ -129,6 +132,7 @@ while [ "$1" != "" ]; do
-rbh | --rabbitmqhost )
if [ "$2" != "" ]; then
RABBITMQ_HOST=$2
check_localhost "$REDIS_HOST" && EXTERNAL_RABBITMQ_FLAG="true"
shift
fi
;;
@ -264,12 +268,14 @@ save_undefined_param() {
restart_services() {
chown -R ${PACKAGE_SYSNAME}:${PACKAGE_SYSNAME} $APP_DIR $PRODUCT_DIR $LOG_DIR /var/www/$PACKAGE_SYSNAME/Data
sed "s_\(ENVIRONMENT=\).*_\1${ENVIRONMENT}_i" -i /usr/lib/systemd/system/${PRODUCT}*.service >/dev/null 2>&1
sed "s_\(ENVIRONMENT=\).*_\1${ENVIRONMENT}_i" -i ${SYSTEMD_DIR}/${PRODUCT}*.service >/dev/null 2>&1
systemctl daemon-reload
echo -n "Updating database... "
systemctl start ${PRODUCT}-migration-runner >/dev/null 2>&1 || true
sleep 15
while systemctl is-active ${PRODUCT}-migration-runner &>/dev/null; do
sleep 5
done
echo "OK"
echo -n "Restarting services... "
@ -458,25 +464,19 @@ change_mysql_config(){
setup_openresty(){
echo -n "Configuring openresty... "
if systemctl list-units --type=service | grep -q nginx; then
systemctl stop nginx && systemctl disable nginx
fi
cp -rf ${APP_DIR}/nginx/nginx.conf.template /usr/local/openresty/nginx/conf/nginx.conf
cp -rf ${APP_DIR}/openresty/nginx.conf.template ${OPENRESTY_CONF}
[ ! -f "${OPENRESTY_DIR}/mime.types" ] && cp -rf "$(dirname ${OPENRESTY_CONF})/mime.types" ${OPENRESTY_DIR}
# Remove default nginx website
rm -f ${NGINX_DIR}/conf.d/default.conf ${NGINX_DIR}/sites-enabled/default
sed 's/\(listen .*:\)\([0-9]\{2,5\}\b\)\( default_server\)\?\(;\)/\1'${APP_PORT}'\3\4/' -i ${NGINX_DIR}/conf.d/${PACKAGE_SYSNAME}-proxy.conf
sed "s!\(^worker_processes\).*;!\1 ${NGINX_WORKER_PROCESSES:-$(grep processor /proc/cpuinfo | wc -l)};!" -i ${NGINX_CONF}
sed "s!\(worker_connections\).*;!\1 ${NGINX_WORKER_CONNECTIONS:-$(ulimit -n)};!" -i ${NGINX_CONF}
sed 's/\(listen .*:\)\([0-9]\{2,5\}\b\)\( default_server\)\?\(;\)/\1'${APP_PORT}'\3\4/' -i ${OPENRESTY_DIR}/conf.d/${PACKAGE_SYSNAME}-proxy.conf
sed "s!\(^worker_processes\).*;!\1 ${NGINX_WORKER_PROCESSES:-$(grep processor /proc/cpuinfo | wc -l)};!" -i "${OPENRESTY_CONF}"
sed "s!\(worker_connections\).*;!\1 ${NGINX_WORKER_CONNECTIONS:-$(ulimit -n)};!" -i "${OPENRESTY_CONF}"
# Check for old configuration files
if [ -f "${NGINX_DIR}/conf.d/onlyoffice-proxy.conf.dpkg-old" ]; then
PROXY_CONF="${NGINX_DIR}/conf.d/onlyoffice-proxy.conf.dpkg-old"
elif [ -f "${NGINX_DIR}/conf.d/onlyoffice-proxy.conf.rpmsave" ]; then
PROXY_CONF="${NGINX_DIR}/conf.d/onlyoffice-proxy.conf.rpmsave"
if [ -f "${OPENRESTY_DIR}/conf.d/${PACKAGE_SYSNAME}-proxy.conf.dpkg-old" ]; then
PROXY_CONF="${OPENRESTY_DIR}/conf.d/${PACKAGE_SYSNAME}-proxy.conf.dpkg-old"
elif [ -f "${OPENRESTY_DIR}/conf.d/${PACKAGE_SYSNAME}-proxy.conf.rpmsave" ]; then
PROXY_CONF="${OPENRESTY_DIR}/conf.d/${PACKAGE_SYSNAME}-proxy.conf.rpmsave"
fi
# If the configuration file is found, extract the paths to the certificate and key
@ -542,7 +542,7 @@ setup_openresty(){
fi
fi
chown nginx:nginx /etc/nginx/* -R
chown nginx:nginx ${OPENRESTY_DIR}* -R
systemctl enable openresty >/dev/null 2>&1
systemctl restart openresty
echo "OK"
@ -570,17 +570,19 @@ setup_docs() {
$JSON ${DS_CONF_DIR}/local.json -e "this.rabbitmq = { 'url': 'amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@${RABBITMQ_HOST}:${RABBITMQ_PORT}' }" >/dev/null 2>&1
$JSON ${DS_CONF_DIR}/local.json -e "this.services.CoAuthoring.redis = { 'host': '$REDIS_HOST' }" >/dev/null 2>&1
sed 's/\(listen .*:\)\([0-9]\{2,5\}\b\)\( default_server\)\?\(;\)/\1'${DOCUMENT_SERVER_PORT}'\3\4/' -i ${DS_CONF_DIR}/nginx/ds.conf
chown ds:ds ${DS_CONF_DIR}/local.json
elif [ $1 == "EXTERNAL_DOCS_SERVER" ]; then
local APP_HOST=$(curl -s ifconfig.me)
local EXTERNAL_DOCS_FLAG="rewrite"
fi
#Changing the Docs port in nginx conf
sed "0,/proxy_pass .*;/{s#proxy_pass .*;#proxy_pass ${DOCUMENT_SERVER_URL_EXTERNAL:-http://$APP_HOST:$DOCUMENT_SERVER_PORT};#}" -i ${NGINX_DIR}/conf.d/${PACKAGE_SYSNAME}.conf
sed "0,/proxy_pass .*;/{s#proxy_pass .*;#proxy_pass ${DOCUMENT_SERVER_URL_EXTERNAL:-http://$APP_HOST:$DOCUMENT_SERVER_PORT};#}" -i ${OPENRESTY_DIR}/conf.d/${PACKAGE_SYSNAME}.conf
#Save Docs address and JWT in .json
save_undefined_param "${USER_CONF}" "files.docservice.secret.value" "${DOCUMENT_SERVER_JWT_SECRET}" "$EXTERNAL_DOCS_FLAG"
save_undefined_param "${USER_CONF}" "files.docservice.secret.header" "${DOCUMENT_SERVER_JWT_HEADER:-"AuthorizationJwt"}" "$EXTERNAL_DOCS_FLAG"
save_undefined_param "${USER_CONF}" "files.docservice.secret.value" "${DOCUMENT_SERVER_JWT_SECRET}" "rewrite"
save_undefined_param "${USER_CONF}" "files.docservice.secret.header" "${DOCUMENT_SERVER_JWT_HEADER:-"AuthorizationJwt"}" "rewrite"
save_undefined_param "${USER_CONF}" "files.docservice.url.public" "${DOCUMENT_SERVER_URL_EXTERNAL:-"/ds-vpath/"}" "$EXTERNAL_DOCS_FLAG"
save_undefined_param "${USER_CONF}" "files.docservice.url.internal" "${DOCUMENT_SERVER_URL_EXTERNAL:-"http://$APP_HOST:$DOCUMENT_SERVER_PORT"}" "$EXTERNAL_DOCS_FLAG"
save_undefined_param "${USER_CONF}" "files.docservice.url.portal" "http://${APP_HOST}:${APP_PORT}" "$EXTERNAL_DOCS_FLAG"
@ -593,7 +595,7 @@ setup_enterprise() {
LICENCE_PATH="/var/www/$PACKAGE_SYSNAME/Data/license.lic"
fi
save_undefined_param "${USER_CONF}" "license.file.path" ${LICENCE_PATH} "rewrite"
save_undefined_param "${USER_CONF}" "license.file.path" "${LICENCE_PATH}" "rewrite"
}
change_elasticsearch_config(){
@ -632,6 +634,18 @@ change_elasticsearch_config(){
sed "/-XX:+HeapDumpOnOutOfMemoryError/d" -i ${ELASTIC_SEARCH_JAVA_CONF_PATH}
fi
if ! grep -q "Dlog4j2.formatMsgNoLookups" ${ELASTIC_SEARCH_JAVA_CONF_PATH}; then
echo "-Dlog4j2.formatMsgNoLookups=true" >> ${ELASTIC_SEARCH_JAVA_CONF_PATH}
else
sed -i "s/Dlog4j2.formatMsgNoLookups.*/Dlog4j2.formatMsgNoLookups=true/" ${ELASTIC_SEARCH_JAVA_CONF_PATH}
fi
if ! grep -q "ingest.geoip.downloader.enabled" ${ELASTIC_SEARCH_CONF_PATH}; then
echo "ingest.geoip.downloader.enabled: false" >> ${ELASTIC_SEARCH_CONF_PATH}
else
sed -i "s/ingest.geoip.downloader.enabled.*/ingest.geoip.downloader.enabled: false/" ${ELASTIC_SEARCH_CONF_PATH}
fi
local TOTAL_MEMORY=$(free -m | grep -oP '\d+' | head -n 1);
local MEMORY_REQUIREMENTS=12228; #RAM ~4*3Gb
@ -658,10 +672,11 @@ setup_elasticsearch() {
echo -n "Configuring elasticsearch... "
#Save elasticsearch parameters in .json
save_undefined_param "${APP_DIR}/elastic.${ENVIRONMENT}.json" "elastic.Scheme" "${ELK_SHEME}"
save_undefined_param "${APP_DIR}/elastic.${ENVIRONMENT}.json" "elastic.Host" "${ELK_HOST}"
save_undefined_param "${APP_DIR}/elastic.${ENVIRONMENT}.json" "elastic.Port" "${ELK_PORT}"
save_undefined_param "${APP_DIR}/elastic.${ENVIRONMENT}.json" "elastic.Threads" "1"
[[ $1 == "EXTERNAL_ELASTIC_SERVER" ]] && local EXTERNAL_ELASTIC_FLAG="rewrite"
save_undefined_param "${APP_DIR}/elastic.${ENVIRONMENT}.json" "elastic.Scheme" "${ELK_SHEME}" "$EXTERNAL_ELASTIC_FLAG"
save_undefined_param "${APP_DIR}/elastic.${ENVIRONMENT}.json" "elastic.Host" "${ELK_HOST}" "$EXTERNAL_ELASTIC_FLAG"
save_undefined_param "${APP_DIR}/elastic.${ENVIRONMENT}.json" "elastic.Port" "${ELK_PORT}" "$EXTERNAL_ELASTIC_FLAG"
save_undefined_param "${APP_DIR}/elastic.${ENVIRONMENT}.json" "elastic.Threads" "1" "$EXTERNAL_ELASTIC_FLAG"
if [ $1 == "LOCAL_ELASTIC_SERVER" ]; then
change_elasticsearch_config
@ -677,8 +692,8 @@ setup_redis() {
$JSON $APP_DIR/redis.$ENVIRONMENT.json -e "this.Redis={'Hosts': [ { Host: \"${REDIS_HOST}\", Port: \"${REDIS_PORT}\" } ] }" >/dev/null 2>&1
sed -i "s~\(redis_host =\).*~\1 \"$REDIS_HOST\"~" "${NGINX_DIR}/conf.d/${PACKAGE_SYSNAME}.conf"
sed -i "s~\(redis_port =\).*~\1 $REDIS_PORT~" "${NGINX_DIR}/conf.d/${PACKAGE_SYSNAME}.conf"
sed -i "s~\(redis_host =\).*~\1 \"$REDIS_HOST\"~" "${OPENRESTY_DIR}/conf.d/${PACKAGE_SYSNAME}.conf"
sed -i "s~\(redis_port =\).*~\1 $REDIS_PORT~" "${OPENRESTY_DIR}/conf.d/${PACKAGE_SYSNAME}.conf"
if [ $1 == "LOCAL_REDIS_SERVER" ]; then
if [ -f "/etc/redis/redis.conf" ]; then
@ -700,10 +715,11 @@ setup_redis() {
setup_rabbitmq() {
echo -n "Configuring rabbitmq... "
save_undefined_param "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.Hostname" "${RABBITMQ_HOST}"
save_undefined_param "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.UserName" "${RABBITMQ_USER}"
save_undefined_param "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.Password" "${RABBITMQ_PASSWORD}"
save_undefined_param "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.Port" "${RABBITMQ_PORT}"
[[ $1 == "EXTERNAL_RABBITMQ_SERVER" ]] && local EXTERNAL_RABBITMQ_FLAG="rewrite"
save_undefined_param "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.Hostname" "${RABBITMQ_HOST}" "$EXTERNAL_RABBITMQ_FLAG"
save_undefined_param "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.UserName" "${RABBITMQ_USER}" "$EXTERNAL_RABBITMQ_FLAG"
save_undefined_param "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.Password" "${RABBITMQ_PASSWORD}" "$EXTERNAL_RABBITMQ_FLAG"
save_undefined_param "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.Port" "${RABBITMQ_PORT}" "$EXTERNAL_RABBITMQ_FLAG"
save_undefined_param "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.VirtualHost" "/"
if [ $1 == "LOCAL_RABBITMQ_SERVER" ]; then
@ -738,7 +754,7 @@ check_connection_external_services() {
HOST_RESPONCE=$?
if [[ $HOST_RESPONCE -ne 0 ]]; then
echo -e "Host is not responding: $1:$2"
echo -e "$3 external server is not responding: $1:$2"
return $HOST_RESPONCE
fi
@ -750,11 +766,13 @@ if command -v yum >/dev/null 2>&1; then
PACKAGE_MANAGER="rpm -q"
MYSQL_PACKAGE="mysqld"
REDIS_PACKAGE="redis"
SYSTEMD_DIR="/usr/lib/systemd/system"
elif command -v apt >/dev/null 2>&1; then
DIST="Debian"
PACKAGE_MANAGER="dpkg -s"
MYSQL_PACKAGE="mysql"
REDIS_PACKAGE="redis-server"
SYSTEMD_DIR="$(dirname $(dpkg-query -L ${PRODUCT}-api | grep systemd/system/))"
fi
install_json
@ -765,41 +783,38 @@ if $PACKAGE_MANAGER mysql-client >/dev/null 2>&1 || $PACKAGE_MANAGER mysql-commu
establish_mysql_conn || exit $?
fi
if $PACKAGE_MANAGER ${PACKAGE_SYSNAME}-documentserver >/dev/null 2>&1 || $PACKAGE_MANAGER ${PACKAGE_SYSNAME}-documentserver-de >/dev/null 2>&1 || $PACKAGE_MANAGER ${PACKAGE_SYSNAME}-documentserver-ee >/dev/null 2>&1; then
if [[ ! -z $DOCUMENT_SERVER_URL_EXTERNAL ]]; then
parse_external_docs_url "$DOCUMENT_SERVER_URL_EXTERNAL"
check_connection_external_services "$DOCUMENT_SERVER_HOST" "$DOCUMENT_SERVER_PORT" "${PACKAGE_SYSNAME^^} Docs"
setup_docs "EXTERNAL_DOCS_SERVER"
elif $PACKAGE_MANAGER ${PACKAGE_SYSNAME}-documentserver >/dev/null 2>&1 || $PACKAGE_MANAGER ${PACKAGE_SYSNAME}-documentserver-de >/dev/null 2>&1 || $PACKAGE_MANAGER ${PACKAGE_SYSNAME}-documentserver-ee >/dev/null 2>&1; then
setup_docs "LOCAL_DOCS_SERVER"
setup_enterprise
elif [[ ! -z $DOCUMENT_SERVER_URL_EXTERNAL ]]; then
parse_external_docs_url "$DOCUMENT_SERVER_URL_EXTERNAL"
check_connection_external_services "$DOCUMENT_SERVER_HOST" "$DOCUMENT_SERVER_PORT" || { echo "ONLYOFFICE Docs host is not responding"; }
setup_docs "EXTERNAL_DOCS_SERVER"
fi
if $PACKAGE_MANAGER openresty >/dev/null 2>&1; then
setup_openresty
fi
if $PACKAGE_MANAGER elasticsearch >/dev/null 2>&1; then
if [[ ! -z $EXTERNAL_ELK_FLAG ]]; then
check_connection_external_services "$ELK_HOST" "$ELK_PORT" "Elasticsearch"
setup_elasticsearch "EXTERNAL_ELASTIC_SERVER"
elif $PACKAGE_MANAGER elasticsearch >/dev/null 2>&1; then
setup_elasticsearch "LOCAL_ELASTIC_SERVER"
elif check_connection_external_services "$ELK_HOST" "$ELK_PORT"; then
setup_elasticsearch "EXTERNAL_ELASTIC_SERVER"
else
echo "Elasticsearch host is not responding"
fi
if $PACKAGE_MANAGER $REDIS_PACKAGE >/dev/null 2>&1 >/dev/null 2>&1; then
if [[ ! -z $EXTERNAL_REDIS_FLAG ]]; then
check_connection_external_services "$REDIS_HOST" "$REDIS_PORT" "Redis"
setup_redis "EXTERNAL_REDIS_SERVER"
elif $PACKAGE_MANAGER $REDIS_PACKAGE >/dev/null 2>&1; then
setup_redis "LOCAL_REDIS_SERVER"
elif check_connection_external_services "$REDIS_HOST" "$REDIS_PORT"; then
setup_redis "EXTERNAL_REDIS_SERVER"
else
echo "Redis host is not responding"
fi
if $PACKAGE_MANAGER rabbitmq-server >/dev/null 2>&1; then
setup_rabbitmq "LOCAL_RABBITMQ_SERVER"
elif check_connection_external_services "$RABBITMQ_HOST" "$RABBITMQ_PORT"; then
if [[ ! -z $EXTERNAL_RABBITMQ_FLAG ]]; then
check_connection_external_services "$RABBITMQ_HOST" "$RABBITMQ_PORT" "RabbitMQ"
setup_rabbitmq "EXTERNAL_RABBITMQ_SERVER"
else
echo "Rabbitmq host is not responding"
elif $PACKAGE_MANAGER rabbitmq-server >/dev/null 2>&1; then
setup_rabbitmq "LOCAL_RABBITMQ_SERVER"
fi
restart_services

View File

@ -5,8 +5,9 @@ set -e
PRODUCT="docspace"
DIR="/usr/bin"
LETSENCRYPT="/etc/letsencrypt/live";
NGINX="/etc/nginx/conf.d"
OPENRESTY="/etc/openresty/conf.d"
DHPARAM_FILE="/etc/ssl/certs/dhparam.pem"
WEBROOT_PATH="/var/www/${PRODUCT}"
if [ "$#" -ge "2" ]; then
if [ "$1" != "-f" ]; then
@ -27,8 +28,8 @@ if [ "$#" -ge "2" ]; then
echo "Generating Let's Encrypt SSL Certificates..."
# Request and generate Let's Encrypt SSL certificate
echo certbot certonly --expand --webroot --noninteractive --agree-tos --email ${MAIL} -d ${DOMAIN} > /var/log/le-start.log
certbot certonly --expand --webroot --noninteractive --agree-tos --email ${MAIL} -d ${DOMAIN} > /var/log/le-new.log
echo certbot certonly --expand --webroot -w ${WEBROOT_PATH} --cert-name ${PRODUCT} --noninteractive --agree-tos --email ${MAIL} -d ${DOMAIN} > /var/log/le-start.log
certbot certonly --expand --webroot -w ${WEBROOT_PATH} --cert-name ${PRODUCT} --noninteractive --agree-tos --email ${MAIL} -d ${DOMAIN} > /var/log/le-new.log
else
echo "Using specified files to configure SSL..."
@ -36,20 +37,20 @@ if [ "$#" -ge "2" ]; then
PRIVATEKEY_FILE=$3
fi
[[ ! -f "${DHPARAM_FILE}" ]] && openssl dhparam -out ${DHPARAM_FILE} 4096
[[ ! -f "${DHPARAM_FILE}" ]] && openssl dhparam -out ${DHPARAM_FILE} 2048
CERTIFICATE_FILE="${CERTIFICATE_FILE:-"${LETSENCRYPT}/${DOMAIN}/fullchain.pem"}"
PRIVATEKEY_FILE="${PRIVATEKEY_FILE:-"${LETSENCRYPT}/${DOMAIN}/privkey.pem"}"
CERTIFICATE_FILE="${CERTIFICATE_FILE:-"${LETSENCRYPT}/${PRODUCT}/fullchain.pem"}"
PRIVATEKEY_FILE="${PRIVATEKEY_FILE:-"${LETSENCRYPT}/${PRODUCT}/privkey.pem"}"
if [ -f "${CERTIFICATE_FILE}" -a -f ${PRIVATEKEY_FILE} ]; then
if [ -f "${NGINX}/onlyoffice-proxy-ssl.conf.template" ]; then
cp -f ${NGINX}/onlyoffice-proxy-ssl.conf.template ${NGINX}/onlyoffice-proxy.conf
if [ -f "${OPENRESTY}/onlyoffice-proxy-ssl.conf.template" ]; then
cp -f ${OPENRESTY}/onlyoffice-proxy-ssl.conf.template ${OPENRESTY}/onlyoffice-proxy.conf
ENVIRONMENT=$(grep -oP 'ENVIRONMENT=\K.*' /usr/lib/systemd/system/${PRODUCT}-api.service)
sed -i "s/\(\"portal\":\).*/\1 \"https:\/\/${DOMAIN:-$(hostname --fqdn)}\"/" /etc/onlyoffice/docspace/appsettings.$ENVIRONMENT.json
sed -i "s~\(ssl_certificate \).*;~\1${CERTIFICATE_FILE};~g" ${NGINX}/onlyoffice-proxy.conf
sed -i "s~\(ssl_certificate_key \).*;~\1${PRIVATEKEY_FILE};~g" ${NGINX}/onlyoffice-proxy.conf
sed -i "s~\(ssl_dhparam \).*;~\1${DHPARAM_FILE};~g" ${NGINX}/onlyoffice-proxy.conf
sed -i "s~\(ssl_certificate \).*;~\1${CERTIFICATE_FILE};~g" ${OPENRESTY}/onlyoffice-proxy.conf
sed -i "s~\(ssl_certificate_key \).*;~\1${PRIVATEKEY_FILE};~g" ${OPENRESTY}/onlyoffice-proxy.conf
sed -i "s~\(ssl_dhparam \).*;~\1${DHPARAM_FILE};~g" ${OPENRESTY}/onlyoffice-proxy.conf
if [[ "${LETSENCRYPT_ENABLE}" = "true" ]]; then
# Create and set permissions for ${PRODUCT}-renew-letsencrypt

View File

@ -8,19 +8,24 @@ db_input low {{product}}/environment || true
db_input low {{product}}/host || true
db_input low {{product}}/port || true
db_input medium {{product}}/elasticsearch-sheme || true
db_input medium {{product}}/elasticsearch-host || true
db_input medium {{product}}/elasticsearch-port || true
db_input low {{product}}/elasticsearch-sheme || true
db_input low {{product}}/elasticsearch-host || true
db_input low {{product}}/elasticsearch-port || true
db_input medium {{product}}/redis-host || true
db_input medium {{product}}/redis-port || true
db_input low {{product}}/redis-host || true
db_input low {{product}}/redis-port || true
db_input medium {{product}}/rabbitmq-host || true
db_input medium {{product}}/rabbitmq-user || true
db_input medium {{product}}/rabbitmq-port || true
db_input medium {{product}}/rabbitmq-password || true
db_input low {{product}}/rabbitmq-host || true
db_input low {{product}}/rabbitmq-user || true
db_input low {{product}}/rabbitmq-port || true
db_input low {{product}}/rabbitmq-password || true
db_input medium {{product}}/db-host || true
db_input low {{product}}/ds-url || true
db_input low {{product}}/jwt-secret || true
db_input low {{product}}/jwt-header || true
db_input low {{product}}/db-host || true
db_input high {{product}}/db-name || true
db_input high {{product}}/db-user || true
db_go

View File

@ -56,7 +56,7 @@ Package: {{product}}-files
Architecture: all
Multi-Arch: foreign
Depends: {{product}}-common (= {{package_header_tag_version}}), dotnet-sdk-7.0, ${misc:Depends}, ${shlibs:Depends}
Recommends: elasticsearch (= 7.10.0)
Recommends: elasticsearch (= 7.16.3)
Description: {{product}}-files
The service which handles API requests related to
documents and launches the OFormService service
@ -65,7 +65,7 @@ Package: {{product}}-files-services
Architecture: all
Multi-Arch: foreign
Depends: {{product}}-common (= {{package_header_tag_version}}), dotnet-sdk-7.0, ${misc:Depends}, ${shlibs:Depends}
Recommends: ffmpeg, elasticsearch (= 7.10.0)
Recommends: ffmpeg, elasticsearch (= 7.16.3)
Description: {{product}}-files-services
The service which launches additional services related to file management:
- ElasticSearchIndexService - indexes documents using elasticsearch;
@ -79,7 +79,7 @@ Package: {{product}}-notify
Architecture: all
Multi-Arch: foreign
Depends: {{product}}-common (= {{package_header_tag_version}}), dotnet-sdk-7.0, ${misc:Depends}, ${shlibs:Depends}
Recommends: ffmpeg, elasticsearch (= 7.10.0)
Recommends: ffmpeg, elasticsearch (= 7.16.3)
Description: {{product}}-notify
The service which launches additional services
related to notifications about DocSpace events:

View File

@ -50,7 +50,7 @@ case "$1" in
db_get {{product}}/redis-port || true
REDIS_PORT="$RET"
args+=(-rdh "$REDIS_HOST" -rdp "$REDIS_PORT" );
[ -n "$REDIS_HOST" ] && args+=(-rdh "$REDIS_HOST" -rdp "$REDIS_PORT" );
db_get {{product}}/rabbitmq-host || true
RABBITMQ_HOST="$RET"
@ -61,8 +61,8 @@ case "$1" in
db_get {{product}}/rabbitmq-password || true
RABBITMQ_PASSWORD="$RET"
args+=(-rbh "$RABBITMQ_HOST" -rbp "$RABBITMQ_PORT" -rbu "$RABBITMQ_USER" -rbpw "$RABBITMQ_PASSWORD" );
[ -n "$RABBITMQ_HOST" ] && args+=(-rbh "$RABBITMQ_HOST" -rbp "$RABBITMQ_PORT" -rbu "$RABBITMQ_USER" -rbpw "$RABBITMQ_PASSWORD" );
db_get {{product}}/elasticsearch-sheme || true
ELK_SHEME="$RET"
db_get {{product}}/elasticsearch-host || true
@ -70,14 +70,22 @@ case "$1" in
db_get {{product}}/elasticsearch-port || true
ELK_PORT="$RET"
args+=(-ess "$ELK_SHEME" -esh "$ELK_HOST" -esp "$ELK_PORT" );
[ -n "$ELK_HOST" ] && args+=(-ess "$ELK_SHEME" -esh "$ELK_HOST" -esp "$ELK_PORT" );
db_get {{product}}/ds-host || true
DOCUMENT_SERVER_HOST="$RET"
db_get {{product}}/ds-port || true
DOCUMENT_SERVER_PORT="$RET"
db_get {{product}}/ds-url || true
DOCUMENT_SERVER_URL_EXTERNAL="$RET"
db_get {{product}}/jwt-secret || true
DOCUMENT_SERVER_JWT_SECRET="$RET"
db_get {{product}}/jwt-header || true
DOCUMENT_SERVER_JWT_HEADER="$RET"
args+=(-dsh "$DOCUMENT_SERVER_HOST" -dsp "$DOCUMENT_SERVER_PORT" );
if [ -n "$DOCUMENT_SERVER_URL_EXTERNAL" ]; then
if [ -n "$DOCUMENT_SERVER_JWT_SECRET" ] && [ -n "$DOCUMENT_SERVER_JWT_HEADER" ]; then
args+=(-docsurl "$DOCUMENT_SERVER_URL_EXTERNAL" -js "$DOCUMENT_SERVER_JWT_SECRET" -jh "$DOCUMENT_SERVER_JWT_HEADER")
else
echo "You should provide JWT-secret and JWT-header along with ONLYOFFICE Docs URL. "
fi
fi
bash /usr/bin/{{product}}-configuration "${args[@]}"

View File

@ -1,8 +1,9 @@
## COPY PUBLIC ##
../../../build/install/common/{{product}}-ssl-setup usr/bin
../../../build/install/docker/config/nginx/templates/*.template etc/onlyoffice/{{product}}/nginx
../../../build/install/docker/config/nginx/onlyoffice* etc/nginx/conf.d
../../../config/nginx/onlyoffice*.conf etc/nginx/conf.d
../../../config/nginx/includes/onlyoffice*.conf etc/nginx/includes
../../../build/install/docker/config/nginx/templates/*.template etc/onlyoffice/{{product}}/openresty
../../../build/install/docker/config/nginx/onlyoffice* etc/openresty/conf.d
../../../config/nginx/onlyoffice*.conf etc/openresty/conf.d
../../../build/install/docker/config/nginx/letsencrypt* etc/openresty/includes
../../../config/nginx/includes/onlyoffice*.conf etc/openresty/includes
../../../build/deploy/public/* var/www/{{product}}/public
../../../build/deploy/client/* var/www/{{product}}/client

View File

@ -0,0 +1,10 @@
#!/bin/bash
set -e
# (DS v1.1.3) Removing old nginx configs to prevent conflicts before upgrading on OpenResty.
if [ -f /etc/nginx/conf.d/onlyoffice.conf ]; then
rm -rf /etc/nginx/conf.d/onlyoffice*
systemctl reload nginx
fi
exit 0

View File

@ -32,15 +32,9 @@ Type: string
Default: onlyoffice
Description: Database name:
Template: {{product}}/ds-host
Template: {{product}}/ds-url
Type: string
Default: localhost
Description: ONLYOFFICE Docs host:
Template: {{product}}/ds-port
Type: string
Default: 8083
Description: ONLYOFFICE Docs port:
Description: ONLYOFFICE Docs URL:
Template: {{product}}/elasticsearch-sheme
Type: select
@ -50,7 +44,6 @@ Description: Elasticsearch protocol:
Template: {{product}}/elasticsearch-host
Type: string
Default: localhost
Description: Elasticsearch host:
Template: {{product}}/elasticsearch-port
@ -60,7 +53,6 @@ Description: Elasticsearch port:
Template: {{product}}/redis-host
Type: string
Default: localhost
Description: Redis host:
Template: {{product}}/redis-port
@ -70,7 +62,6 @@ Description: Redis port:
Template: {{product}}/rabbitmq-host
Type: string
Default: localhost
Description: RabbitMQ host:
Template: {{product}}/rabbitmq-port
@ -91,3 +82,11 @@ Description: RabbitMQ password:
Template: {{product}}/machinekey
Type: string
Description: Enter your own machinekey:
Template: {{product}}/jwt-header
Type: string
Description: Enter JWT header:
Template: {{product}}/jwt-secret
Type: string
Description: Enter JWT secret:

View File

@ -45,13 +45,15 @@ override_dh_auto_build:
-e "this.ssoauth={ 'path': '../ASC.SsoAuth/' }" -e "this.logLevel=\"warning\"" -e "this.core={ 'products': { 'folder': '/var/www/${PRODUCT}/products', 'subfolder': 'server'} }"
find ${SRC_PATH}/config/ -type f -regex '.*\.\(test\|dev\).*' -delete
json -I -f ${SRC_PATH}/config/appsettings.json -e "this.core.notify.postman=\"services\"" -e "this.Logging.LogLevel.Default=\"Warning\"" -e "this['debug-info'].enabled=\"false\""
json -I -f ${SRC_PATH}/config/appsettings.json -e "this.core.notify.postman=\"services\"" -e "this.Logging.LogLevel.Default=\"Warning\"" -e "this['debug-info'].enabled=\"false\"" -e "this.web.samesite=\"None\""
json -I -f ${SRC_PATH}/config/apisystem.json -e "this.core.notify.postman=\"services\""
sed 's_\(minlevel=\)".*"_\1"Warn"_g' -i ${SRC_PATH}/config/nlog.config
sed 's_etc/nginx_etc/openresty_g' -i ${SRC_PATH}/config/nginx/*.conf
sed 's/teamlab.info/onlyoffice.com/g' -i ${SRC_PATH}/config/autofac.consumers.json
sed -e 's/$$router_host/127.0.0.1/g' -e '/proxy_set_header/d' -i ${SRC_PATH}/build/install/docker/config/nginx/onlyoffice-proxy*.conf
sed -e '/.pid/d' -e '/temp_path/d' -i ${SRC_PATH}/build/install/docker/config/nginx/templates/nginx.conf.template
sed -e 's/$$router_host/127.0.0.1/g' -e 's/the_host/host/g' -e 's/the_scheme/scheme/g' -e 's_includes_/etc/openresty/includes_g' -i ${SRC_PATH}/build/install/docker/config/nginx/onlyoffice-proxy*.conf
sed "s_\(.*root\).*;_\1 \"/var/www/${PRODUCT}\";_g" -i ${SRC_PATH}/build/install/docker/config/nginx/letsencrypt.conf
sed -e '/.pid/d' -e '/temp_path/d' -e 's_etc/nginx_etc/openresty_g' -i ${SRC_PATH}/build/install/docker/config/nginx/templates/nginx.conf.template
mv -f ${SRC_PATH}/build/install/docker/config/nginx/onlyoffice-proxy-ssl.conf ${SRC_PATH}/build/install/docker/config/nginx/onlyoffice-proxy-ssl.conf.template
for i in ${PRODUCT} $$(ls ${CURRENT_PATH}/debian/*.install | grep -oP 'debian/\K.*' | grep -o '^[^.]*'); do \

View File

@ -53,3 +53,17 @@ library-not-linked-against-libc
# Some file triggers a privacy concern, specifically references an image files .png
privacy-breach-generic
# Building a cross-platform project, so those files are arch-independent
arch-independent-package-contains-binary-or-object
# Specifying a dependency on glibc would be redundant and could create unnecessary dependencies.
# We tested the application in different environments and made sure that it works stably without explicit dependence on glibc.
missing-dependency-on-libc
# Some binary files are executable, but are not intended for debugging.
# Including debug symbols in these files makes no sense and increases the size of the package.
unstripped-binary-or-object
# The systemctl call is used to manage MySQL and ensure that it is configured correctly
maintainer-script-calls-systemctl

View File

@ -8,7 +8,7 @@
CONTAINER_PREFIX=${PRODUCT}-
MYSQL_VERSION=8.0.32
MYSQL_IMAGE=mysql:${MYSQL_VERSION}
ELK_VERSION=7.10.0
ELK_VERSION=7.16.3
SERVICE_PORT=5050
DOCUMENT_SERVER_IMAGE_NAME=onlyoffice/4testing-documentserver-ee:latest
DOCKERFILE=Dockerfile.app

View File

@ -7,6 +7,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
DOCKERCOMPOSE=$(dirname "$DIR")
LETSENCRYPT="/etc/letsencrypt/live";
DHPARAM_FILE="/etc/ssl/certs/dhparam.pem"
WEBROOT_PATH="/letsencrypt"
if [ "$#" -ge "2" ]; then
if [ "$1" != "-f" ]; then
@ -15,7 +16,7 @@ if [ "$#" -ge "2" ]; then
LETSENCRYPT_ENABLE="true"
if [ -f "${DOCKERCOMPOSE}/proxy.yml" ]; then
docker-compose -f ${DOCKERCOMPOSE}/proxy.yml down
:
elif [ -f "/app/onlyoffice/proxy.yml" ]; then
DOCKERCOMPOSE="/app/onlyoffice"
DIR="/app/onlyoffice/config"
@ -23,14 +24,25 @@ if [ "$#" -ge "2" ]; then
echo "Error: proxy configuration file not found." && exit 1
fi
if ! docker ps -f "name=onlyoffice-proxy" --format '{{.Names}}' | grep -q "onlyoffice-proxy"; then
echo "Error: the proxy container is not running" && exit 1
fi
if ! docker volume inspect "onlyoffice_webroot_path" &> /dev/null; then
echo "Error: missing webroot_path volume" && exit 1
fi
echo "Generating Let's Encrypt SSL Certificates..."
# Request and generate Let's Encrypt SSL certificate
docker run -it --rm \
-v /etc/letsencrypt:/etc/letsencrypt \
-v /var/lib/letsencrypt:/var/lib/letsencrypt \
-v /var/log:/var/log \
-v onlyoffice_webroot_path:${WEBROOT_PATH} \
certbot/certbot certonly \
--webroot --non-interactive --agree-tos --email ${MAIL} -d ${DOMAIN}
--expand --webroot -w ${WEBROOT_PATH} \
--cert-name ${PRODUCT} --non-interactive --agree-tos --email ${MAIL} -d ${DOMAIN}
else
echo "Using specified files to configure SSL..."
@ -38,14 +50,19 @@ if [ "$#" -ge "2" ]; then
PRIVATEKEY_FILE=$3
fi
[[ ! -f "${DHPARAM_FILE}" ]] && openssl dhparam -out ${DHPARAM_FILE} 4096
[[ ! -f "${DHPARAM_FILE}" ]] && openssl dhparam -out ${DHPARAM_FILE} 2048
CERTIFICATE_FILE="${CERTIFICATE_FILE:-"${LETSENCRYPT}/${DOMAIN}/fullchain.pem"}"
PRIVATEKEY_FILE="${PRIVATEKEY_FILE:-"${LETSENCRYPT}/${DOMAIN}/privkey.pem"}"
CERTIFICATE_FILE="${CERTIFICATE_FILE:-"${LETSENCRYPT}/${PRODUCT}/fullchain.pem"}"
PRIVATEKEY_FILE="${PRIVATEKEY_FILE:-"${LETSENCRYPT}/${PRODUCT}/privkey.pem"}"
if [ -f "${CERTIFICATE_FILE}" -a -f ${PRIVATEKEY_FILE} ]; then
if [ -f ${DOCKERCOMPOSE}/.env -a -f ${DOCKERCOMPOSE}/proxy-ssl.yml ]; then
sed -i "s~\(APP_URL_PORTAL=\).*~\1\"https://${DOMAIN:-$(hostname --fqdn)}\"~g" ${DOCKERCOMPOSE}/.env
docker-compose -f ${DOCKERCOMPOSE}/proxy.yml down
docker-compose -f ${DOCKERCOMPOSE}/docspace.yml stop onlyoffice-files
if [[ ! -z "$DOMAIN" ]] || [[ "$(grep 'APP_URL_PORTAL=' ${DOCKERCOMPOSE}/.env)" != *"https://"* ]]; then
sed -i "s~\(APP_URL_PORTAL=\).*~\1\"https://${DOMAIN:-$(hostname --fqdn)}\"~g" ${DOCKERCOMPOSE}/.env
fi
sed -i "s~\(CERTIFICATE_PATH=\).*~\1\"${CERTIFICATE_FILE}\"~g" ${DOCKERCOMPOSE}/.env
sed -i "s~\(CERTIFICATE_KEY_PATH=\).*~\1\"${PRIVATEKEY_FILE}\"~g" ${DOCKERCOMPOSE}/.env
sed -i "s~\(DHPARAM_PATH=\).*~\1\"${DHPARAM_FILE}\"~g" ${DOCKERCOMPOSE}/.env
@ -69,6 +86,7 @@ if [ "$#" -ge "2" ]; then
fi
docker-compose -f ${DOCKERCOMPOSE}/proxy-ssl.yml up -d
docker-compose -f ${DOCKERCOMPOSE}/docspace.yml up -d onlyoffice-files
echo "OK"
else

View File

@ -0,0 +1,4 @@
location ~ /.well-known/acme-challenge {
root "/letsencrypt";
allow all;
}

View File

@ -16,12 +16,26 @@ server {
rewrite ^ https://$host$request_uri? permanent;
}
server {
listen 127.0.0.1:80;
listen [::1]:80;
server_name localhost;
client_max_body_size 4G;
location / {
proxy_pass http://$router_host:8092;
}
}
## HTTPS host
server {
listen 0.0.0.0:443 ssl;
listen [::]:443 ssl default_server;
root /usr/share/nginx/html;
client_max_body_size 4G;
## Strong SSL Security
## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
ssl_certificate /usr/local/share/ca-certificates/tls.crt;
@ -58,4 +72,5 @@ server {
proxy_pass http://$router_host:8092;
}
include includes/letsencrypt.conf;
}

View File

@ -9,7 +9,11 @@ server {
listen 0.0.0.0:80;
listen [::]:80 default_server;
client_max_body_size 4G;
location / {
proxy_pass http://$router_host:8092;
}
include includes/letsencrypt.conf;
}

View File

@ -37,6 +37,7 @@ APP_KNOWN_PROXIES = os.environ["APP_KNOWN_PROXIES"]
APP_KNOWN_NETWORKS = os.environ["APP_KNOWN_NETWORKS"]
LOG_LEVEL = os.environ["LOG_LEVEL"] if environ.get("LOG_LEVEL") else None
DEBUG_INFO = os.environ["DEBUG_INFO"] if environ.get("DEBUG_INFO") else "false"
SAMESITE = os.environ["SAMESITE"] if environ.get("SAMESITE") else "None"
DOCUMENT_CONTAINER_NAME = os.environ["DOCUMENT_CONTAINER_NAME"] if environ.get("DOCUMENT_CONTAINER_NAME") else "onlyoffice-document-server"
DOCUMENT_SERVER_JWT_SECRET = os.environ["DOCUMENT_SERVER_JWT_SECRET"] if environ.get("DOCUMENT_SERVER_JWT_SECRET") else "your_jwt_secret"
@ -167,6 +168,7 @@ updateJsonData(jsonData,"$.files.docservice.secret.value", DOCUMENT_SERVER_JWT_S
updateJsonData(jsonData,"$.files.docservice.secret.header", DOCUMENT_SERVER_JWT_HEADER)
updateJsonData(jsonData,"$.Logging.LogLevel.Default", LOG_LEVEL)
updateJsonData(jsonData,"$.debug-info.enabled", DEBUG_INFO)
updateJsonData(jsonData,"$.web.samesite", SAMESITE)
if INSTALLATION_TYPE == "ENTERPRISE":
updateJsonData(jsonData, "$.license.file.path", "/app/onlyoffice/data/license.lic")

View File

@ -74,6 +74,7 @@ services:
- "ES_JAVA_OPTS=-Xms4g -Xmx4g -Dlog4j2.formatMsgNoLookups=true"
- "indices.fielddata.cache.size=30%"
- "indices.memory.index_buffer_size=30%"
- "ingest.geoip.downloader.enabled=false"
ulimits:
memlock:
soft: -1

View File

@ -10,6 +10,7 @@ services:
- "ES_JAVA_OPTS=-Xms4g -Xmx4g -Dlog4j2.formatMsgNoLookups=true"
- "indices.fielddata.cache.size=30%"
- "indices.memory.index_buffer_size=30%"
- "ingest.geoip.downloader.enabled=false"
ulimits:
memlock:
soft: -1

View File

@ -39,5 +39,5 @@ volumes:
networks:
default:
external:
name: "onlyoffice"
name: ${NETWORK_NAME}
external: true

View File

@ -21,8 +21,10 @@ services:
environment:
- ROUTER_HOST=${ROUTER_HOST}
volumes:
- webroot_path:/letsencrypt
- proxy_log:/var/log/nginx
- ./config/nginx/templates/nginx.conf.template:/etc/nginx/nginx.conf
- ./config/nginx/letsencrypt.conf:/etc/nginx/includes/letsencrypt.conf
- ./config/nginx/templates/proxy.upstream.conf.template:/etc/nginx/templates/proxy.upstream.conf.template:ro
- ./config/nginx/onlyoffice-proxy-ssl.conf:/etc/nginx/conf.d/default.conf
- ${CERTIFICATE_PATH}:/usr/local/share/ca-certificates/tls.crt
@ -36,3 +38,4 @@ networks:
volumes:
proxy_log:
webroot_path:

View File

@ -20,8 +20,10 @@ services:
environment:
- ROUTER_HOST=${ROUTER_HOST}
volumes:
- webroot_path:/letsencrypt
- proxy_log:/var/log/nginx
- ./config/nginx/templates/nginx.conf.template:/etc/nginx/nginx.conf
- ./config/nginx/letsencrypt.conf:/etc/nginx/includes/letsencrypt.conf
- ./config/nginx/templates/proxy.upstream.conf.template:/etc/nginx/templates/proxy.upstream.conf.template:ro
- ./config/nginx/onlyoffice-proxy.conf:/etc/nginx/conf.d/default.conf
@ -32,3 +34,4 @@ networks:
volumes:
proxy_log:
webroot_path:

View File

@ -57,3 +57,15 @@ addFilter(r'W: binary-or-shlib-calls-gethostbyname')
# There are the same files, however on a different languages
addFilter(r'files-duplicate')
# Building a cross-platform project, so those files are arch-independent
addFilter(r'arch-independent-package-contains-binary-or-object')
# File is a static library that is used when building our application.
# The presence of an executable bit on it is justified, since the object files that are used for linking when building the program are included.
# /var/www/{{product}}/services/ASC.Web.HealthChecks.UI/runtimes/browser-wasm/nativeassets/net7.0/e_sqlite3.a
addFilter(r'spurious-executable-perm')
addFilter(r'devel-file-in-non-devel-package')
# Necessary to resolve a config conflict
addFilter(r'dangerous-command-in-%pre')

View File

@ -16,13 +16,15 @@ json -I -f %{_builddir}/%{sourcename}/config/appsettings.services.json -e "this.
-e "this.ssoauth={ 'path': '../ASC.SsoAuth/' }" -e "this.logLevel=\"warning\"" -e "this.core={ 'products': { 'folder': '%{buildpath}/products', 'subfolder': 'server'} }"
find %{_builddir}/%{sourcename}/config/ -type f -regex '.*\.\(test\|dev\).*' -delete
json -I -f %{_builddir}/%{sourcename}/config/appsettings.json -e "this.core.notify.postman=\"services\"" -e "this.Logging.LogLevel.Default=\"Warning\"" -e "this['debug-info'].enabled=\"false\""
json -I -f %{_builddir}/%{sourcename}/config/appsettings.json -e "this.core.notify.postman=\"services\"" -e "this.Logging.LogLevel.Default=\"Warning\"" -e "this['debug-info'].enabled=\"false\"" -e "this.web.samesite=\"None\""
json -I -f %{_builddir}/%{sourcename}/config/apisystem.json -e "this.core.notify.postman=\"services\""
sed 's_\(minlevel=\)".*"_\1"Warn"_g' -i %{_builddir}/%{sourcename}/config/nlog.config
sed 's_etc/nginx_etc/openresty_g' -i %{_builddir}/%{sourcename}/config/nginx/*.conf
sed 's/teamlab.info/onlyoffice.com/g' -i %{_builddir}/%{sourcename}/config/autofac.consumers.json
sed -e 's/$router_host/127.0.0.1/g' -e '/proxy_set_header/d' -i %{_builddir}/%{sourcename}/build/install/docker/config/nginx/onlyoffice-proxy*.conf
sed -e '/.pid/d' -e '/temp_path/d' -i %{_builddir}/%{sourcename}/build/install/docker/config/nginx/templates/nginx.conf.template
sed -e 's/$router_host/127.0.0.1/g' -e 's/the_host/host/g' -e 's/the_scheme/scheme/g' -e 's_includes_/etc/openresty/includes_g' -i %{_builddir}/%{sourcename}/build/install/docker/config/nginx/onlyoffice-proxy*.conf
sed -e '/.pid/d' -e '/temp_path/d' -e 's_etc/nginx_etc/openresty_g' -i %{_builddir}/%{sourcename}/build/install/docker/config/nginx/templates/nginx.conf.template
sed -i "s_\(.*root\).*;_\1 \"/var/www/%{product}\";_g" -i %{_builddir}/%{sourcename}/build/install/docker/config/nginx/letsencrypt.conf
find %{_builddir}/%{sourcename}/publish/ \
%{_builddir}/%{sourcename}/ASC.Migration.Runner \

View File

@ -31,6 +31,7 @@
%files common
%defattr(-, onlyoffice, onlyoffice, -)
%config %attr(640, onlyoffice, onlyoffice) %{_sysconfdir}/onlyoffice/%{product}/*
%exclude %{_sysconfdir}/onlyoffice/%{product}/openresty
%exclude %{_sysconfdir}/onlyoffice/%{product}/nginx
%{_docdir}/%{name}-%{version}-%{release}/
%config %{_sysconfdir}/logrotate.d/%{product}-common
@ -73,13 +74,13 @@
%files proxy
%defattr(-, onlyoffice, onlyoffice, -)
%config %{_sysconfdir}/nginx/includes/*
%config %{_sysconfdir}/nginx/conf.d/*
%config %{_sysconfdir}/openresty/includes/*
%config %{_sysconfdir}/openresty/conf.d/*
%attr(744, root, root) %{_bindir}/%{product}-ssl-setup
%config %{_sysconfdir}/onlyoffice/%{product}/nginx/nginx.conf.template
%config %{_sysconfdir}/onlyoffice/%{product}/openresty/nginx.conf.template
%dir %{_sysconfdir}/onlyoffice/
%dir %{_sysconfdir}/onlyoffice/%{product}/
%dir %{_sysconfdir}/onlyoffice/%{product}/nginx/
%dir %{_sysconfdir}/onlyoffice/%{product}/openresty/
%{buildpath}/public/
%{buildpath}/client/

View File

@ -3,9 +3,10 @@ rm -rf %{buildroot}
mkdir -p "%{buildroot}%{_bindir}/"
mkdir -p "%{buildroot}%{_docdir}/%{name}-%{version}-%{release}/"
mkdir -p "%{buildroot}%{_sysconfdir}/logrotate.d"
mkdir -p "%{buildroot}%{_sysconfdir}/nginx/conf.d/"
mkdir -p "%{buildroot}%{_sysconfdir}/nginx/includes/"
mkdir -p "%{buildroot}%{_sysconfdir}/openresty/conf.d/"
mkdir -p "%{buildroot}%{_sysconfdir}/openresty/includes/"
mkdir -p "%{buildroot}%{_sysconfdir}/onlyoffice/%{product}/.private/"
mkdir -p "%{buildroot}%{_sysconfdir}/onlyoffice/%{product}/openresty"
mkdir -p "%{buildroot}%{_var}/log/onlyoffice/%{product}/"
mkdir -p "%{buildroot}%{buildpath}/Tools/radicale/plugins/"
mkdir -p "%{buildroot}%{buildpath}/products/ASC.Files/client/"
@ -43,8 +44,8 @@ cp -rf %{_builddir}/%{sourcename}/build/install/common/%{product}-configuration
cp -rf %{_builddir}/%{sourcename}/build/install/common/systemd/modules/* "%{buildroot}/usr/lib/systemd/system/"
cp -rf %{_builddir}/%{sourcename}/build/install/common/logrotate/product-common "%{buildroot}%{_sysconfdir}/logrotate.d/%{product}-common"
cp -rf %{_builddir}/%{sourcename}/config/* "%{buildroot}%{_sysconfdir}/onlyoffice/%{product}/"
cp -rf %{_builddir}/%{sourcename}/config/nginx/includes/onlyoffice*.conf "%{buildroot}%{_sysconfdir}/nginx/includes/"
cp -rf %{_builddir}/%{sourcename}/config/nginx/onlyoffice*.conf "%{buildroot}%{_sysconfdir}/nginx/conf.d/"
cp -rf %{_builddir}/%{sourcename}/config/nginx/includes/onlyoffice*.conf "%{buildroot}%{_sysconfdir}/openresty/includes/"
cp -rf %{_builddir}/%{sourcename}/config/nginx/onlyoffice*.conf "%{buildroot}%{_sysconfdir}/openresty/conf.d/"
cp -rf %{_builddir}/%{sourcename}/products/ASC.Files/Server/DocStore/* "%{buildroot}%{buildpath}/products/ASC.Files/server/DocStore/"
cp -rf %{_builddir}/%{sourcename}/publish/products/ASC.Files/server/* "%{buildroot}%{buildpath}/products/ASC.Files/server/"
cp -rf %{_builddir}/%{sourcename}/publish/products/ASC.People/server/* "%{buildroot}%{buildpath}/products/ASC.People/server/"
@ -60,7 +61,8 @@ cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Studio.Notify/service/* "
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Web.Api/service/* "%{buildroot}%{buildpath}/studio/ASC.Web.Api/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Web.HealthChecks.UI/service/* "%{buildroot}%{buildpath}/services/ASC.Web.HealthChecks.UI/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Web.Studio/service/* "%{buildroot}%{buildpath}/studio/ASC.Web.Studio/"
cp -rf %{_builddir}/%{sourcename}/build/install/docker/config/nginx/onlyoffice-proxy.conf "%{buildroot}%{_sysconfdir}/nginx/conf.d/onlyoffice-proxy.conf"
cp -rf %{_builddir}/%{sourcename}/build/install/docker/config/nginx/onlyoffice-proxy-ssl.conf "%{buildroot}%{_sysconfdir}/nginx/conf.d/onlyoffice-proxy-ssl.conf.template"
cp -rf %{_builddir}/%{sourcename}/build/install/docker/config/nginx/templates/nginx.conf.template "%{buildroot}%{_sysconfdir}/onlyoffice/%{product}/nginx/nginx.conf.template"
cp -rf %{_builddir}/%{sourcename}/build/install/docker/config/nginx/onlyoffice-proxy.conf "%{buildroot}%{_sysconfdir}/openresty/conf.d/onlyoffice-proxy.conf"
cp -rf %{_builddir}/%{sourcename}/build/install/docker/config/nginx/onlyoffice-proxy-ssl.conf "%{buildroot}%{_sysconfdir}/openresty/conf.d/onlyoffice-proxy-ssl.conf.template"
cp -rf %{_builddir}/%{sourcename}/build/install/docker/config/nginx/letsencrypt.conf "%{buildroot}%{_sysconfdir}/openresty/includes/letsencrypt.conf"
cp -rf %{_builddir}/%{sourcename}/build/install/docker/config/nginx/templates/nginx.conf.template "%{buildroot}%{_sysconfdir}/onlyoffice/%{product}/openresty/nginx.conf.template"
cp -rf %{_builddir}/%{sourcename}/build/install/common/%{product}-ssl-setup "%{buildroot}%{_bindir}/%{product}-ssl-setup"

View File

@ -77,6 +77,14 @@ mv -f %{_builddir}/dictionaries-master/* %{_builddir}/%{sourcename}/common/Test
getent group onlyoffice >/dev/null || groupadd -r onlyoffice
getent passwd onlyoffice >/dev/null || useradd -r -g onlyoffice -s /sbin/nologin onlyoffice
%pre proxy
# (DS v1.1.3) Removing old nginx configs to prevent conflicts before upgrading on OpenResty.
if [ -f /etc/nginx/conf.d/onlyoffice.conf ]; then
rm -rf /etc/nginx/conf.d/onlyoffice*
systemctl reload nginx
fi
%post
%preun

View File

@ -43,6 +43,7 @@
<ROW Property="MsiLogging" MultiBuildValue="DefaultBuild:vp"/>
<ROW Property="MySQLConnector" Value="MySQL Connector/ODBC 8.0.21 x86"/>
<ROW Property="NEED_REINDEX_ELASTICSEARCH" Value="FALSE"/>
<ROW Property="OPEN_INSTALL_CANCEL_URL" Value="1"/>
<ROW Property="PACKAGE_NAME" Value="ONLYOFFICE_DocSpace_Enterprise_Win-install.v[|ProductVersion]"/>
<ROW Property="PRODUCT_NAME" Value="ONLYOFFICE DocSpace Enterprise"/>
<ROW Property="PS_DB_HOST" Value="localhost"/>
@ -70,8 +71,8 @@
<ROW Property="WindowsTypeNT50Display" MultiBuildValue="DefaultBuild:Windows 2000" ValueLocId="-"/>
<ROW Property="WindowsTypeNT5X" MultiBuildValue="DefaultBuild:Windows XP/2003" ValueLocId="-"/>
<ROW Property="WindowsTypeNT5XDisplay" MultiBuildValue="DefaultBuild:Windows XP/2003" ValueLocId="-"/>
<ROW Property="WindowsTypeNT64" MultiBuildValue="DefaultBuild:Windows Vista x64, Windows Server 2008 x64, Windows 7 x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows 8.1 x64, Windows 10 x64, Windows 11 x64" ValueLocId="-"/>
<ROW Property="WindowsTypeNT64Display" MultiBuildValue="DefaultBuild:Windows Vista x64, Windows Server 2008 x64, Windows 7 x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows 8.1 x64, Windows 10 x64, Windows 11 x64" ValueLocId="-"/>
<ROW Property="WindowsTypeNT64" MultiBuildValue="DefaultBuild:Windows Vista x64, Windows Server 2008 x64, Windows 7 x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows Server 2012 x64, Windows 8.1 x64, Windows Server 2012 R2 x64, Windows 10 x64, Windows 11 x64" ValueLocId="-"/>
<ROW Property="WindowsTypeNT64Display" MultiBuildValue="DefaultBuild:Windows Vista x64, Windows Server 2008 x64, Windows 7 x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows Server 2012 x64, Windows 8.1 x64, Windows Server 2012 R2 x64, Windows 10 x64, Windows 11 x64" ValueLocId="-"/>
<ROW Property="WindowsTypeNTDisplay" MultiBuildValue="DefaultBuild:32-bit Windows versions" ValueLocId="-"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">
@ -200,6 +201,7 @@
<ROW Name="lzmaextractor.dll" SourcePath="&lt;AI_CUSTACTS&gt;lzmaextractor.dll"/>
<ROW Name="msichainer.exe" SourcePath="&lt;AI_CUSTACTS&gt;msichainer.exe"/>
<ROW Name="utils.vbs" SourcePath="utils.vbs"/>
<ROW Name="viewer.exe" SourcePath="&lt;AI_CUSTACTS&gt;viewer.exe" DigSign="true"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiControlComponent">
<ROW Dialog_="AdminBrowseDlg" Control="OK" Type="PushButton" X="304" Y="243" Width="56" Height="17" Attributes="3" Text="[ButtonText_OK]" Order="300" TextLocId="-" MsiKey="AdminBrowseDlg#OK"/>
@ -368,7 +370,7 @@
<ROW Dialog_="ProgressPrereqDlg" Control="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" Attributes="1048577" Text="banner.bmp" Order="400" MsiKey="ProgressPrereqDlg#BannerBitmap"/>
<ROW Dialog_="ProgressPrereqDlg" Control="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" Attributes="1" Order="600" MsiKey="ProgressPrereqDlg#BannerLine"/>
<ROW Dialog_="ProgressPrereqDlg" Control="ActionText" Type="Text" X="80" Y="100" Width="255" Height="10" Attributes="3" Order="700" MsiKey="ProgressPrereqDlg#ActionText"/>
<ROW Dialog_="ProgressPrereqDlg" Control="Title" Type="Text" X="20" Y="15" Width="250" Height="15" Attributes="196611" Text="[Progress1] prerequisites for [ProductName]" TextStyle="[DlgTitleFont]" Order="800" TextLocId="Control.Text.ProgressPrereqDlg#Title" MsiKey="ProgressPrereqDlg#Title"/>
<ROW Dialog_="ProgressPrereqDlg" Control="Title" Type="Text" X="20" Y="15" Width="250" Height="20" Attributes="196611" Text="[Progress1] prerequisites for [ProductName]" TextStyle="[DlgTitleFont]" Order="800" TextLocId="Control.Text.ProgressPrereqDlg#Title" MsiKey="ProgressPrereqDlg#Title"/>
<ROW Dialog_="ProgressPrereqDlg" Control="Text" Type="Text" X="35" Y="65" Width="300" Height="30" Attributes="196611" Text="Please wait while the [Wizard] [Progress2] prerequisites for [ProductName]. This may take several minutes." Order="900" TextLocId="Control.Text.ProgressPrereqDlg#Text" MsiKey="ProgressPrereqDlg#Text"/>
<ROW Dialog_="ProgressPrereqDlg" Control="StatusLabel" Type="Text" X="35" Y="100" Width="45" Height="10" Attributes="3" Text="Status:" Order="1000" TextLocId="Control.Text.ProgressPrereqDlg#StatusLabel" MsiKey="ProgressPrereqDlg#StatusLabel"/>
<ROW Dialog_="ProgressPrereqDlg" Control="ProgressBar" Type="ProgressBar" X="35" Y="115" Width="300" Height="10" Attributes="65537" Text="Progress done" Order="1100" TextLocId="Control.Text.ProgressPrereqDlg#ProgressBar" MsiKey="ProgressPrereqDlg#ProgressBar"/>
@ -495,6 +497,7 @@
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="DoAction" Argument="TestSqlConnection" Condition="AI_INSTALL" Ordering="1"/>
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="SQLConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError &lt;&gt; &quot;&quot; AND OLDPRODUCTS &lt;&gt; &quot;&quot; )" Ordering="20"/>
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL AND ( SqlConnectionError = &quot;&quot; AND PostgreSqlConnectionError = &quot;&quot; AND ELK_CONNECTION = &quot;True&quot; AND RabbitMQServerConnectionError = &quot;&quot; AND RedisServerConnectionError = &quot;&quot; AND OLDPRODUCTS &lt;&gt; &quot;&quot; )" Ordering="25"/>
<ROW Dialog_="CancelDlg" Control_="Yes" Event="DoAction" Argument="OpenCancelUrl" Condition="OPEN_INSTALL_CANCEL_URL = &quot;1&quot;" Ordering="101"/>
<ROW Dialog_="FolderDlg" Control_="Next" Event="DoAction" Argument="TestSqlConnection" Condition="AI_INSTALL" Ordering="201"/>
<ROW Dialog_="FolderDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL AND ( SqlConnectionError = &quot;&quot; AND PostgreSqlConnectionError = &quot;&quot; AND ELK_CONNECTION = &quot;True&quot; AND RabbitMQServerConnectionError = &quot;&quot; AND RedisServerConnectionError = &quot;&quot; )" Ordering="222"/>
<ROW Dialog_="SQLConnectionDlg" Control_="Next" Event="DoAction" Argument="TestSqlConnection" Condition="AI_INSTALL" Ordering="3"/>
@ -553,6 +556,8 @@
<ROW Dialog_="SQLConnectionDlg" Control_="Next" Event="NewDialog" Argument="ELKConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError = &quot;&quot; AND PostgreSqlConnectionError = &quot;&quot; AND ELK_CONNECTION = &quot;False&quot; )" Ordering="9"/>
<ROW Dialog_="PostgreSQLConnectionDlg" Control_="Back" Event="NewDialog" Argument="FolderDlg" Condition="AI_INSTALL AND ( OLDPRODUCTS = &quot;&quot; )" Ordering="1"/>
<ROW Dialog_="PostgreSQLConnectionDlg" Control_="Back" Event="NewDialog" Argument="WelcomeDlg" Condition="AI_INSTALL AND ( OLDPRODUCTS &lt;&gt; &quot;&quot; )" Ordering="2"/>
<ROW Dialog_="CancelDlg" Control_="No" Event="EndDialog" Argument="Return" Condition="1" Ordering="100" MsiKey="CancelDlg#No#EndDialog#Return#1"/>
<ROW Dialog_="CancelDlg" Control_="Yes" Event="EndDialog" Argument="Exit" Condition="1" Ordering="100" MsiKey="CancelDlg#Yes#EndDialog#Exit#1"/>
<ROW Dialog_="FolderDlg" Control_="Next" Event="DoAction" Argument="TestPostgreSqlConnection" Condition="AI_INSTALL AND ( SqlConnectionError = &quot;&quot; )" Ordering="210"/>
<ROW Dialog_="FolderDlg" Control_="Next" Event="NewDialog" Argument="PostgreSQLConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError = &quot;&quot; AND PostgreSqlConnectionError &lt;&gt; &quot;&quot; )" Ordering="217"/>
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="PostgreSQLConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError = &quot;&quot; AND PostgreSqlConnectionError &lt;&gt; &quot;&quot; AND OLDPRODUCTS &lt;&gt; &quot;&quot; )" Ordering="21"/>
@ -584,7 +589,7 @@
<ROW Action="AI_ConfigureChainer" Type="1" Source="Prereq.dll" Target="ConfigurePrereqLauncher"/>
<ROW Action="AI_DATA_SETTER" Type="51" Source="CustomActionData" Target="[AI_SETUPEXEPATH]"/>
<ROW Action="AI_DATA_SETTER_1" Type="51" Source="CustomActionData" Target="HOST=[ELASTICSEARCH_HOST];PORT=[ELASTICSEARCH_PORT];OUTPUT=ELK_CONNECTION"/>
<ROW Action="AI_DATA_SETTER_10" Type="51" Source="StartWebApi" Target="ASC.WebApi"/>
<ROW Action="AI_DATA_SETTER_10" Type="51" Source="StartWebApi" Target="DocSpace.WebApi"/>
<ROW Action="AI_DATA_SETTER_2" Type="51" Source="CustomActionData" Target="[ELASTICSEARCH_MSG]&#13;\n[ELASTICSEARCH_SCHEME]://[ELASTICSEARCH_HOST]:[ELASTICSEARCH_PORT] |[ProductName] Setup |MB_OK,MB_ICONWARNING,MB_DEFBUTTON1||[CLIENTPROCESSID]"/>
<ROW Action="AI_DATA_SETTER_3" Type="51" Source="CustomActionData" Target="[PostgreSqlConnectionError] |[ProductName] Setup |MB_OK,MB_ICONWARNING,MB_DEFBUTTON1||[CLIENTPROCESSID]"/>
<ROW Action="AI_DATA_SETTER_4" Type="51" Source="CustomActionData" Target="[RabbitMQServerConnectionError] |[ProductName] Setup |MB_OK,MB_ICONWARNING,MB_DEFBUTTON1||[CLIENTPROCESSID]"/>
@ -592,7 +597,7 @@
<ROW Action="AI_DATA_SETTER_6" Type="51" Source="CustomActionData" Target="[SqlConnectionError] |[ProductName] Setup |MB_OK,MB_ICONWARNING,MB_DEFBUTTON1||[CLIENTPROCESSID]"/>
<ROW Action="AI_DATA_SETTER_7" Type="51" Source="CustomActionData" Target="[~]"/>
<ROW Action="AI_DATA_SETTER_8" Type="51" Source="CustomActionData" Target="[~]"/>
<ROW Action="AI_DATA_SETTER_9" Type="51" Source="StopWebApi" Target="ASC.WebApi"/>
<ROW Action="AI_DATA_SETTER_9" Type="51" Source="StopWebApi" Target="DocSpace.WebApi"/>
<ROW Action="AI_DOWNGRADE" Type="19" Target="4010"/>
<ROW Action="AI_DeleteCadLzma" Type="51" Source="AI_DeleteLzma" Target="[AI_SETUPEXEPATH]"/>
<ROW Action="AI_DeleteLzma" Type="1025" Source="lzmaextractor.dll" Target="DeleteLZMAFiles"/>
@ -628,6 +633,7 @@
<ROW Action="AI_VerifyPrereq" Type="1" Source="Prereq.dll" Target="VerifyPrereq"/>
<ROW Action="EnterpriseConfigure" Type="6" Source="utils.vbs" Target="EnterpriseConfigure"/>
<ROW Action="MySQLConfigure" Type="6" Source="utils.vbs" Target="MySQLConfigure"/>
<ROW Action="OpenCancelUrl" Type="194" Source="viewer.exe" Target="http://www.onlyoffice.com/install-canceled.aspx" WithoutSeq="true" Options="1"/>
<ROW Action="PostgreSqlConfigure" Type="4102" Source="utils.vbs" Target="PostgreSqlConfigure"/>
<ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]" MultiBuildTarget="DefaultBuild:[ProgramFilesFolder][INSTALL_ROOT_FOLDER_NAME]\DocSpace"/>
<ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]" MultiBuildTarget="DefaultBuild:[ProgramMenuFolder][INSTALL_ROOT_FOLDER_NAME]\DocSpace"/>
@ -727,7 +733,7 @@
<ROW Action="SetDocumentServerJWTSecretProp" Condition="( ( NOT Installed ) OR ( Installed AND REMOVE &lt;&gt; &quot;ALL&quot; AND AI_INSTALL_MODE &lt;&gt; &quot;Remove&quot; ) ) AND ( JWT_ENABLED = &quot;true&quot; AND NOT DOCSPACE_INSTALLED )" Sequence="1103"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent">
<ROW Condition="( Version9X OR ( NOT VersionNT64 ) OR ( VersionNT64 AND ((VersionNT64 &lt;&gt; 600) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 600) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 601) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 601) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 602) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 603) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 1000) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 1100) OR (MsiNTProductType &lt;&gt; 1)) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT64Display]." DescriptionLocId="AI.LaunchCondition.NoSpecificNT64" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="( Version9X OR ( NOT VersionNT64 ) OR ( VersionNT64 AND ((VersionNT64 &lt;&gt; 600) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 600) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 601) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 601) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 602) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 602) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 603) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 603) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 1000) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 1100) OR (MsiNTProductType &lt;&gt; 1)) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT64Display]." DescriptionLocId="AI.LaunchCondition.NoSpecificNT64" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="( Version9X OR VersionNT64 )" Description="[ProductName] cannot be installed on [WindowsTypeNTDisplay]." DescriptionLocId="AI.LaunchCondition.NoNT" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="((VersionNT &lt;&gt; 501) AND (VersionNT &lt;&gt; 502))" Description="[ProductName] cannot be installed on [WindowsTypeNT5XDisplay]." DescriptionLocId="AI.LaunchCondition.NoNT5X" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="(VersionNT &lt;&gt; 400)" Description="[ProductName] cannot be installed on [WindowsTypeNT40Display]." DescriptionLocId="AI.LaunchCondition.NoNT40" IsPredefined="true" Builds="DefaultBuild"/>
@ -823,8 +829,9 @@
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.PreReqComponent">
<ROW PrereqKey="CA62D813A4E74FA2AAE86A7D7B7B1493" DisplayName="Visual C++ Redistributable for Visual Studio 2013 Update 5 x64" VersionMin="12.0" SetupFileUrl="redist\vcredist_2013u5_x64.exe" Location="0" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/q /norestart" BasicUiComLine="/q /norestart" NoUiComLine="/q /norestart" Options="xym" TargetName="Visual C++ Redistributable for Visual Studio 2013\vcredist_2013u5_x64.exe"/>
<ROW PrereqKey="Certbot" DisplayName="Certbot" VersionMin="2.6.0" SetupFileUrl="redist\certbot-2.6.0.exe" Location="0" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/S" BasicUiComLine="/S" NoUiComLine="/S" Options="yx" TargetName="Certbot\certbot-beta-installer-win_amd64_signed.exe"/>
<ROW PrereqKey="EA5B60A5CAD4115A8386D017CC889B9" DisplayName="ASP.NET Core Runtime 7.0.4 x64" VersionMin="7.0" SetupFileUrl="redist\aspnetcore-runtime-7.0.4-win-x64.exe" Location="0" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" WinNT64Versions="Windows Vista x64, Windows Server 2008 x64, Windows 7 RTM x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows Server 2012 x64, Windows 10 version 1507 x64, Windows 10 version 1511 x64" Operator="1" ComLine="/q /norestart" BasicUiComLine="/q /norestart" NoUiComLine="/q /norestart" Options="xym" TargetName="ASP.NET Core 7.0\aspnetcore-runtime-7.0.4-win-x64.exe"/>
<ROW PrereqKey="Elasticsearch7.10.0" DisplayName="Elasticsearch v7.10.0 x64" VersionMin="7.10" SetupFileUrl="redist\elasticsearch-7.10.0.msi" Location="0" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/quiet" BasicUiComLine="/quiet" NoUiComLine="/quiet" Options="y" TargetName="Elasticsearch 7.10.0 x64\elasticsearch-7.10.0.msi"/>
<ROW PrereqKey="Elasticsearch7.16.3" DisplayName="Elasticsearch v7.16.3 x64" VersionMin="7.16.3" SetupFileUrl="redist\elasticsearch-7.16.3.msi" Location="0" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/quiet" BasicUiComLine="/quiet" NoUiComLine="/quiet" Options="y" TargetName="Elasticsearch 7.16.3 x64\elasticsearch-7.16.3.msi"/>
<ROW PrereqKey="F3520F64DA5998338D97129FAD2" DisplayName=".NET Runtime 7.0.4 x64" VersionMin="7.0" SetupFileUrl="redist\dotnet-runtime-7.0.4-win-x64.exe" Location="0" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" WinNT64Versions="Windows Vista x64, Windows Server 2008 x64, Windows 7 RTM x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows Server 2012 x64, Windows 10 version 1507 x64, Windows 10 version 1511 x64" Operator="1" ComLine="/q /norestart" BasicUiComLine="/q /norestart" NoUiComLine="/q /norestart" Options="ym" TargetName=".NET 7.0\dotnet-runtime-7.0.4-win-x64.exe"/>
<ROW PrereqKey="FFmpegEssentials" DisplayName="FFmpeg x64" VersionMin="6.0.0" SetupFileUrl="redist\FFmpeg_Essentials.msi" Location="0" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/quiet" BasicUiComLine="/quiet" NoUiComLine="/quiet" Options="yx" TargetName="FFmpeg x64\FFmpeg_Essentials.msi"/>
<ROW PrereqKey="Microsoft.NETFrame" DisplayName=".NET Framework 4.8" VersionMin="4.8" SetupFileUrl="redist\.net_framework_4.8.exe" Location="0" ExactSize="0" WinNTVersions="Windows Vista x86, Windows Server 2008 x86, Windows 7 RTM x86, Windows 8 x86, Windows 10 version 1507 x86, Windows 10 version 1511 x86, Windows 10 version 1903 x86, Windows 10 version 1909 x86, Windows 10 version 2004 x86, Windows 10 version 20H2 x86, Windows 10 version 21H1 x86" WinNT64Versions="Windows Vista x64, Windows Server 2008 x64, Windows 7 RTM x64, Windows Server 2008 R2 RTM x64, Windows 8 x64, Windows 10 version 1507 x64, Windows 10 version 1511 x64, Windows 10 version 1903 x64, Windows 10 version 1909 x64, Windows 10 version 2004 x64, Windows 10 version 20H2 x64, Windows 10 version 21H1 x64" Operator="1" ComLine="/q /promptrestart" BasicUiComLine="/q /promptrestart" NoUiComLine="/q /promptrestart" Options="yxm" TargetName="Microsoft .NET Framework 4.8\.net_framework_4.8.exe"/>
@ -841,7 +848,7 @@
<ROW PrereqKey="RedisonWindows" DisplayName="Redis 5.0.10 x64" VersionMin="5.0" SetupFileUrl="redist\Redis-x64-5.0.10.msi" Location="0" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/quiet ADD_INSTALLFOLDER_TO_PATH=1" BasicUiComLine="/quiet ADD_INSTALLFOLDER_TO_PATH=1" NoUiComLine="/quiet ADD_INSTALLFOLDER_TO_PATH=1" Options="yx" TargetName="Redis 5.0.10 x64\Redis-x64-5.0.10.msi"/>
<ROW PrereqKey="RequiredApplication" DisplayName="Erlang v26.0.2 x64" VersionMin="26.0.2" SetupFileUrl="redist\otp_win64_26.0.2.exe" Location="0" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/S" BasicUiComLine="/S" NoUiComLine="/S" Options="yx" TargetName="Erlang v26.0.2 x64\otp_win64_26.0.2.exe"/>
<ROW PrereqKey="psqlODBC_x64" DisplayName="PostgreSQL ODBC Driver x64" SetupFileUrl="redist\psqlodbc_15_x64.msi" Location="0" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/quiet" BasicUiComLine="/quiet" NoUiComLine="/quiet" Options="myx" TargetName="psqlodbc_x64.msi"/>
<ATTRIBUTE name="PrereqsOrder" value="Microsoft.NETFrame F3520F64DA5998338D97129FAD2 EA5B60A5CAD4115A8386D017CC889B9 CA62D813A4E74FA2AAE86A7D7B7B1493 MicrosoftVisualC_2 MicrosoftVisualC_3 MySQLConnectorODBC MySQLInstallerCo MySQLInstallerRunn Node.js Elasticsearch7.10.0 RequiredApplication RabbitMQServer RedisonWindows FFmpegEssentials psqlODBC_x64 PostgreSQL OpenResty ONLYOFFICEDocumentS"/>
<ATTRIBUTE name="PrereqsOrder" value="Microsoft.NETFrame F3520F64DA5998338D97129FAD2 EA5B60A5CAD4115A8386D017CC889B9 CA62D813A4E74FA2AAE86A7D7B7B1493 MicrosoftVisualC_2 MicrosoftVisualC_3 MySQLConnectorODBC MySQLInstallerCo MySQLInstallerRunn Node.js Elasticsearch7.16.3 RequiredApplication RabbitMQServer RedisonWindows FFmpegEssentials Certbot psqlODBC_x64 PostgreSQL OpenResty ONLYOFFICEDocumentS"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.PreReqSearchComponent">
<ROW SearchKey="CA62D813A4E74FA2AAE86A7D7B7B1493Ver" Prereq="CA62D813A4E74FA2AAE86A7D7B7B1493" SearchType="2" SearchString="HKLM\SOFTWARE\Microsoft\DevDiv\VC\Servicing\12.0\RuntimeMinimum\Version" VerMin="12.0.40649" Order="1" Property="PreReqSearch_CA62D813A4E74FA2AAE86A"/>
@ -853,6 +860,7 @@
<ROW SearchKey="SystemFolderfile.dll_10" Prereq="RequiredApplication" SearchType="5" SearchString="HKLM\SOFTWARE\Wow6432Node\Ericsson\Erlang\14.0.2" Order="1" Property="PreReqSearch_19"/>
<ROW SearchKey="SystemFolderfile.dll_11" Prereq="RabbitMQServer" SearchType="2" SearchString="HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\RabbitMQ\DisplayVersion" VerMin="3.12.1" Order="1" Property="PreReqSearch_20"/>
<ROW SearchKey="SystemFolderfile.dll_12" Prereq="PostgreSQL" SearchType="5" SearchString="HKLM\SOFTWARE\PostgreSQL\Installations\postgresql-x64-14" Order="1" Property="PreReqSearch_24"/>
<ROW SearchKey="SystemFolderfile.dll_2" Prereq="Certbot" SearchType="2" SearchString="HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Certbot\DisplayVersion" VerMin="2.6.0" Order="1" Property="PreReqSearch_2"/>
<ROW SearchKey="SystemFolderfile.dll_3" Prereq="OpenResty" SearchType="4" SearchString="{264FA774-91E5-4854-8010-4AB58CA830BD}" VerMin="1.21.4.2" Order="1" Property="PreReqSearch_8"/>
<ROW SearchKey="SystemFolderfile.dll_7" Prereq="MicrosoftVisualC_2" SearchType="2" SearchString="HKLM\SOFTWARE\Microsoft\DevDiv\VC\Servicing\14.0\RuntimeMinimum\Version" VerMin="14.26" Order="1" Property="PreReqSearch_9"/>
<ROW SearchKey="SystemFolderfile.dll_8" Prereq="MicrosoftVisualC_3" SearchType="2" SearchString="HKLM\SOFTWARE\Microsoft\DevDiv\VC\Servicing\14.0\RuntimeMinimum\Version" VerMin="14.26" Order="1" Property="PreReqSearch_11"/>
@ -861,7 +869,7 @@
<ROW SearchKey="UpgradeCode" Prereq="MySQLConnectorODBC" SearchType="4" SearchString="{7AEDB3F3-7B9D-4FE2-8D8F-3CE3DE6F5B6B}" VerMin="8.0.33" Order="1" Property="PreReqSearch_12"/>
<ROW SearchKey="UpgradeCode_1" Prereq="MySQLInstallerCo" SearchType="4" SearchString="{18B94B70-06F1-4AC0-B308-37280DB868C2}" VerMin="1.6.6.0" Order="1" Property="PreReqSearch_13"/>
<ROW SearchKey="UpgradeCode_2" Prereq="Node.js" SearchType="4" SearchString="{47C07A3A-42EF-4213-A85D-8F5A59077C28}" VerMin="18.16.0" Order="1" Property="PreReqSearch_17"/>
<ROW SearchKey="UpgradeCode_3" Prereq="Elasticsearch7.10.0" SearchType="4" SearchString="{DAAA2CBA-A1ED-4F29-AFBF-5478617B00F6}" VerMin="7.10.0" Order="1" Property="PreReqSearch_18"/>
<ROW SearchKey="UpgradeCode_3" Prereq="Elasticsearch7.16.3" SearchType="4" SearchString="{DAAA2CBA-A1ED-4F29-AFBF-5478617B00F6}" VerMin="7.16.3" Order="1" Property="PreReqSearch_18"/>
<ROW SearchKey="UpgradeCode_4" Prereq="RedisonWindows" SearchType="4" SearchString="{05410198-7212-4FC4-B7C8-AFEFC3DA0FBC}" VerMin="5.0.10" Order="1" Property="PreReqSearch_21"/>
<ROW SearchKey="UpgradeCode_5" Prereq="FFmpegEssentials" SearchType="4" SearchString="{384A74EC-865A-4907-8561-9DE765EE6E14}" VerMin="6.0.0.20230306" Order="1" Property="PreReqSearch_22"/>
<ROW SearchKey="UpgradeCode_6" Prereq="psqlODBC_x64" SearchType="4" SearchString="{BBD29DF5-89F6-4B8B-BDC9-C3EA3A4AFDBB}" VerMin="15.0" Order="1" Property="PreReqSearch_23"/>

View File

@ -57,6 +57,7 @@
<ROW Property="MsiLogging" MultiBuildValue="DefaultBuild:vp#ExeBuild:vp"/>
<ROW Property="MySQLConnector" Value="MySQL Connector/ODBC 8.0.21 x86"/>
<ROW Property="NEED_REINDEX_ELASTICSEARCH" Value="FALSE" ValueLocId="-"/>
<ROW Property="OPEN_INSTALL_CANCEL_URL" Value="1"/>
<ROW Property="PACKAGE_NAME" Value="ONLYOFFICE_DocSpace_Community_Win-install.v[|ProductVersion]" MultiBuildValue="ExeBuild:ONLYOFFICE_DocSpace_Win-install"/>
<ROW Property="PRODUCT_NAME" Value="ONLYOFFICE DocSpace Community" MultiBuildValue="ExeBuild:ONLYOFFICE DocSpace Enterprise"/>
<ROW Property="PS_DB_HOST" Value="localhost"/>
@ -74,23 +75,23 @@
<ROW Property="REDIS_PWD" Value=" " Options="1" ValueLocId="-"/>
<ROW Property="SUBFOLDER_SERVER" Value="--core:products:subfolder=server"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND;AI_SETUPEXEPATH;SETUPEXEDIR"/>
<ROW Property="ServiceName_ApiSystemService" Value="ASC.ApiSystemService"/>
<ROW Property="ServiceName_BackgroundTasks" Value="ASC.Data.Backup.BackgroundTasks"/>
<ROW Property="ServiceName_BackupService" Value="ASC.BackupService"/>
<ROW Property="ServiceName_ClearEvents" Value="ASC.ClearEvents"/>
<ROW Property="ServiceName_DocEditor" Value="ASC.DocEditor"/>
<ROW Property="ServiceName_FileServer" Value="ASC.FileServer"/>
<ROW Property="ServiceName_FileService" Value="ASC.FileService"/>
<ROW Property="ServiceName_WebHealthChecksUI" Value="ASC.Web.HealthChecks.UI"/>
<ROW Property="ServiceName_Login" Value="ASC.Login"/>
<ROW Property="ServiceName_MigrationRunner" Value="ASC.MigrationRunner"/>
<ROW Property="ServiceName_NotifyService" Value="ASC.NotifyService"/>
<ROW Property="ServiceName_PeopleServer" Value="ASC.PeopleServer"/>
<ROW Property="ServiceName_Socket.IO" Value="ASC.Socket.IO"/>
<ROW Property="ServiceName_SsoAuth" Value="ASC.SsoAuth.Svc"/>
<ROW Property="ServiceName_StudioNotifyService" Value="ASC.StudioNotifyService"/>
<ROW Property="ServiceName_WebApi" Value="ASC.WebApi"/>
<ROW Property="ServiceName_WebStudio" Value="ASC.WebStudio"/>
<ROW Property="ServiceName_ApiSystemService" Value="DocSpace.ApiSystemService"/>
<ROW Property="ServiceName_BackgroundTasks" Value="DocSpace.Data.Backup.BackgroundTasks"/>
<ROW Property="ServiceName_BackupService" Value="DocSpace.BackupService"/>
<ROW Property="ServiceName_ClearEvents" Value="DocSpace.ClearEvents"/>
<ROW Property="ServiceName_DocEditor" Value="DocSpace.DocEditor"/>
<ROW Property="ServiceName_FileServer" Value="DocSpace.FileServer"/>
<ROW Property="ServiceName_FileService" Value="DocSpace.FileService"/>
<ROW Property="ServiceName_WebHealthChecksUI" Value="DocSpace.Web.HealthChecks.UI"/>
<ROW Property="ServiceName_Login" Value="DocSpace.Login"/>
<ROW Property="ServiceName_MigrationRunner" Value="DocSpace.MigrationRunner"/>
<ROW Property="ServiceName_NotifyService" Value="DocSpace.NotifyService"/>
<ROW Property="ServiceName_PeopleServer" Value="DocSpace.PeopleServer"/>
<ROW Property="ServiceName_Socket.IO" Value="DocSpace.Socket.IO"/>
<ROW Property="ServiceName_SsoAuth" Value="DocSpace.SsoAuth.Svc"/>
<ROW Property="ServiceName_StudioNotifyService" Value="DocSpace.StudioNotifyService"/>
<ROW Property="ServiceName_WebApi" Value="DocSpace.WebApi"/>
<ROW Property="ServiceName_WebStudio" Value="DocSpace.WebStudio"/>
<ROW Property="ShortProductName" Value="ONLYOFFICE DocSpace"/>
<ROW Property="Socket.IO_Port" Value="9899"/>
<ROW Property="SsoAuth_Port" Value="9834"/>
@ -104,8 +105,8 @@
<ROW Property="WindowsTypeNT50Display" MultiBuildValue="DefaultBuild:Windows 2000#ExeBuild:Windows 2000" ValueLocId="-"/>
<ROW Property="WindowsTypeNT5X" MultiBuildValue="DefaultBuild:Windows XP/2003#ExeBuild:Windows XP/2003" ValueLocId="-"/>
<ROW Property="WindowsTypeNT5XDisplay" MultiBuildValue="DefaultBuild:Windows XP/2003#ExeBuild:Windows XP/2003" ValueLocId="-"/>
<ROW Property="WindowsTypeNT64" MultiBuildValue="DefaultBuild:Windows Vista x64, Windows Server 2008 x64, Windows 7 x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows 8.1 x64, Windows 10 x64, Windows 11 x64#ExeBuild:Windows Vista x64, Windows Server 2008 x64, Windows 7 x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows 8.1 x64, Windows 10 x64, Windows 11 x64" ValueLocId="-"/>
<ROW Property="WindowsTypeNT64Display" MultiBuildValue="DefaultBuild:Windows Vista x64, Windows Server 2008 x64, Windows 7 x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows 8.1 x64, Windows 10 x64, Windows 11 x64#ExeBuild:Windows Vista x64, Windows Server 2008 x64, Windows 7 x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows 8.1 x64, Windows 10 x64, Windows 11 x64" ValueLocId="-"/>
<ROW Property="WindowsTypeNT64" MultiBuildValue="DefaultBuild:Windows Vista x64, Windows Server 2008 x64, Windows 7 x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows Server 2012 x64, Windows 8.1 x64, Windows Server 2012 R2 x64, Windows 10 x64, Windows 11 x64#ExeBuild:Windows Vista x64, Windows Server 2008 x64, Windows 7 x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows Server 2012 x64, Windows 8.1 x64, Windows Server 2012 R2 x64, Windows 10 x64, Windows 11 x64" ValueLocId="-"/>
<ROW Property="WindowsTypeNT64Display" MultiBuildValue="DefaultBuild:Windows Vista x64, Windows Server 2008 x64, Windows 7 x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows Server 2012 x64, Windows 8.1 x64, Windows Server 2012 R2 x64, Windows 10 x64, Windows 11 x64#ExeBuild:Windows Vista x64, Windows Server 2008 x64, Windows 7 x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows Server 2012 x64, Windows 8.1 x64, Windows Server 2012 R2 x64, Windows 10 x64, Windows 11 x64" ValueLocId="-"/>
<ROW Property="WindowsTypeNTDisplay" MultiBuildValue="DefaultBuild:32-bit Windows versions#ExeBuild:32-bit Windows versions" ValueLocId="-"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">
@ -850,6 +851,7 @@
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="DoAction" Argument="TestElasticsearchConnection" Condition="AI_INSTALL" Ordering="16"/>
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="DoAction" Argument="AI_DATA_SETTER_1" Condition="AI_INSTALL" Ordering="15"/>
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="ELKConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError = &quot;&quot; AND PostgreSqlConnectionError = &quot;&quot; AND ELK_CONNECTION = &quot;False&quot; AND OLDPRODUCTS &lt;&gt; &quot;&quot; )" Ordering="22"/>
<ROW Dialog_="CancelDlg" Control_="Yes" Event="DoAction" Argument="OpenCancelUrl" Condition="OPEN_INSTALL_CANCEL_URL = &quot;1&quot;" Ordering="101"/>
<ROW Dialog_="FolderDlg" Control_="Next" Event="DoAction" Argument="TestElasticsearchConnection" Condition="AI_INSTALL AND ( SqlConnectionError=&quot;&quot; AND PostgreSqlConnectionError = &quot;&quot; )" Ordering="212"/>
<ROW Dialog_="FolderDlg" Control_="Next" Event="DoAction" Argument="AI_DATA_SETTER_1" Condition="AI_INSTALL AND ( SqlConnectionError=&quot;&quot; AND PostgreSqlConnectionError = &quot;&quot; )" Ordering="211"/>
<ROW Dialog_="FolderDlg" Control_="Next" Event="NewDialog" Argument="ELKConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError = &quot;&quot; AND PostgreSqlConnectionError = &quot;&quot; AND ELK_CONNECTION = &quot;False&quot; )" Ordering="218"/>
@ -893,6 +895,8 @@
<ROW Dialog_="SQLConnectionDlg" Control_="Next" Event="NewDialog" Argument="ELKConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError = &quot;&quot; AND PostgreSqlConnectionError = &quot;&quot; AND ELK_CONNECTION = &quot;False&quot; )" Ordering="9"/>
<ROW Dialog_="PostgreSQLConnectionDlg" Control_="Back" Event="NewDialog" Argument="FolderDlg" Condition="AI_INSTALL AND ( OLDPRODUCTS = &quot;&quot; )" Ordering="1"/>
<ROW Dialog_="PostgreSQLConnectionDlg" Control_="Back" Event="NewDialog" Argument="WelcomeDlg" Condition="AI_INSTALL AND ( OLDPRODUCTS &lt;&gt; &quot;&quot; )" Ordering="2"/>
<ROW Dialog_="CancelDlg" Control_="No" Event="EndDialog" Argument="Return" Condition="1" Ordering="100" MsiKey="CancelDlg#No#EndDialog#Return#1"/>
<ROW Dialog_="CancelDlg" Control_="Yes" Event="EndDialog" Argument="Exit" Condition="1" Ordering="100" MsiKey="CancelDlg#Yes#EndDialog#Exit#1"/>
<ROW Dialog_="FolderDlg" Control_="Next" Event="DoAction" Argument="TestPostgreSqlConnection" Condition="AI_INSTALL AND ( SqlConnectionError = &quot;&quot; )" Ordering="210"/>
<ROW Dialog_="FolderDlg" Control_="Next" Event="NewDialog" Argument="PostgreSQLConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError = &quot;&quot; AND PostgreSqlConnectionError &lt;&gt; &quot;&quot; )" Ordering="217"/>
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="PostgreSQLConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError = &quot;&quot; AND PostgreSqlConnectionError &lt;&gt; &quot;&quot; AND OLDPRODUCTS &lt;&gt; &quot;&quot; )" Ordering="21"/>
@ -1058,6 +1062,7 @@
<ROW Action="ElasticSearchSetup" Type="6" Source="utils.vbs" Target="ElasticSearchSetup"/>
<ROW Action="MoveNginxConfigs" Type="6" Source="utils.vbs" Target="MoveNginxConfigs"/>
<ROW Action="MySQLConfigure" Type="262" Source="utils.vbs" Target="MySQLConfigure"/>
<ROW Action="OpenCancelUrl" Type="194" Source="viewer.exe" Target="http://www.onlyoffice.com/install-canceled.aspx" WithoutSeq="true" Options="1"/>
<ROW Action="PostgreSQLConfigure" Type="4102" Source="utils.vbs" Target="PostgreSqlConfigure"/>
<ROW Action="RedisSearchSetup" Type="6" Source="utils.vbs" Target="RedisSetup"/>
<ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]" MultiBuildTarget="DefaultBuild:[ProgramFilesFolder][INSTALL_ROOT_FOLDER_NAME]\DocSpace#ExeBuild:[ProgramFilesFolder][INSTALL_ROOT_FOLDER_NAME]\DocSpace"/>
@ -1292,7 +1297,7 @@
<ROW Action="AI_RestartElevated" Sequence="51" Builds="ExeBuild"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent">
<ROW Condition="( Version9X OR ( NOT VersionNT64 ) OR ( VersionNT64 AND ((VersionNT64 &lt;&gt; 600) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 600) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 601) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 601) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 602) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 603) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 1000) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 1100) OR (MsiNTProductType &lt;&gt; 1)) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT64Display]." DescriptionLocId="AI.LaunchCondition.NoSpecificNT64" IsPredefined="true" Builds="DefaultBuild;ExeBuild"/>
<ROW Condition="( Version9X OR ( NOT VersionNT64 ) OR ( VersionNT64 AND ((VersionNT64 &lt;&gt; 600) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 600) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 601) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 601) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 602) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 602) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 603) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 603) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 1000) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 1100) OR (MsiNTProductType &lt;&gt; 1)) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT64Display]." DescriptionLocId="AI.LaunchCondition.NoSpecificNT64" IsPredefined="true" Builds="DefaultBuild;ExeBuild"/>
<ROW Condition="( Version9X OR VersionNT64 )" Description="[ProductName] cannot be installed on [WindowsTypeNTDisplay]." DescriptionLocId="AI.LaunchCondition.NoNT" IsPredefined="true" Builds="DefaultBuild;ExeBuild"/>
<ROW Condition="((VersionNT &lt;&gt; 501) AND (VersionNT &lt;&gt; 502))" Description="[ProductName] cannot be installed on [WindowsTypeNT5XDisplay]." DescriptionLocId="AI.LaunchCondition.NoNT5X" IsPredefined="true" Builds="DefaultBuild;ExeBuild"/>
<ROW Condition="(VersionNT &lt;&gt; 400)" Description="[ProductName] cannot be installed on [WindowsTypeNT40Display]." DescriptionLocId="AI.LaunchCondition.NoNT40" IsPredefined="true" Builds="DefaultBuild;ExeBuild"/>
@ -1524,6 +1529,7 @@
<ROW PrereqKey="C4FE6FD5B7C4D07B3A313E754A9A6A8" DisplayName="Visual C++ Redistributable for Visual Studio 2015-2019 x64" VersionMin="14.26" SetupFileUrl="https://download.visualstudio.microsoft.com/download/pr/d60aa805-26e9-47df-b4e3-cd6fcc392333/7D7105C52FCD6766BEEE1AE162AA81E278686122C1E44890712326634D0B055E/VC_redist.x64.exe" Location="1" ExactSize="14974616" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" WinNT64Versions="Windows Vista RTM x64, Windows Vista SP1 x64, Windows Server 2008 RTM x64, Windows 7 RTM x64, Windows Server 2008 R2 RTM x64" Operator="1" ComLine="/q /norestart" BasicUiComLine="/q /norestart" NoUiComLine="/q /norestart" Options="xym" MD5="264c296cc0bf00db6ba8e7bf8cc4e706" TargetName="Visual C++ Redistributable for Visual Studio 2015-2019"/>
<ROW PrereqKey="F3520F64DA5998338D97129FAD2" DisplayName=".NET Runtime 7.0.3 x64" VersionMin="7.0" SetupFileUrl="https://download.visualstudio.microsoft.com/download/pr/c69813b7-2ece-4c2e-8c45-e33006985e18/61cc8fe4693a662b2da55ad932a46446/dotnet-runtime-7.0.3-win-x64.exe" Location="1" ExactSize="28223424" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" WinNT64Versions="Windows Vista x64, Windows Server 2008 x64, Windows 7 RTM x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows Server 2012 x64, Windows 10 version 1507 x64, Windows 10 version 1511 x64" Operator="1" ComLine="/q /norestart" BasicUiComLine="/q /norestart" NoUiComLine="/q /norestart" Options="ym" MD5="c9d6796b57a1630d4f004302262c241e" TargetName=".NET 7.0"/>
<ROW PrereqKey="CA62D813A4E74FA2AAE86A7D7B7B1493" DisplayName="Visual C++ Redistributable for Visual Studio 2013 Update 5 x64" VersionMin="12.0" SetupFileUrl="http://download.microsoft.com/download/C/C/2/CC2DF5F8-4454-44B4-802D-5EA68D086676/vcredist_x64.exe" Location="1" ExactSize="7201056" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/quiet" BasicUiComLine="/quiet" NoUiComLine="/quiet" Options="xym" MD5="b364dd867258dfc79342e00d57c81bb5" TargetName="Visual C++ Redistributable for Visual Studio 2013?vcredist_2013u5_x64.exe"/>
<ROW PrereqKey="Certbot" DisplayName="Certbot" VersionMin="2.6.0" SetupFileUrl="https://github.com/certbot/certbot/releases/download/v2.6.0/certbot-beta-installer-win_amd64_signed.exe" Location="1" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/S" BasicUiComLine="/S" NoUiComLine="/S" Options="yx" TargetName="Certbot"/>
<ROW PrereqKey="DocumentServer" DisplayName="DocumentServer" SetupFileUrl="onlyoffice-documentserver.exe" Location="0" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/VERYSILENT /norestart /DIR=&quot;[APPDIR]..\DocumentServer&quot; /DS_PORT=&quot;[DOCUMENT_SERVER_PORT]&quot; /JWT_ENABLED=&quot;[DOCUMENT_SERVER_JWT_ENABLED]&quot; /JWT_SECRET=&quot;[DOCUMENT_SERVER_JWT_SECRET]&quot; /JWT_HEADER=&quot;[DOCUMENT_SERVER_JWT_HEADER]&quot; /DB_HOST=&quot;[PS_DB_HOST]&quot; /DB_USER=&quot;[PS_DB_USER]&quot; /DB_PWD=&quot;[PS_DB_PWD]&quot; /DB_NAME=&quot;[PS_DB_NAME]&quot; /LOG" BasicUiComLine="/VERYSILENT /norestart /DIR=&quot;[APPDIR]..\DocumentServer&quot; /DS_PORT=&quot;[DOCUMENT_SERVER_PORT]&quot; /JWT_ENABLED=&quot;[DOCUMENT_SERVER_JWT_ENABLED]&quot; /JWT_SECRET=&quot;[DOCUMENT_SERVER_JWT_SECRET]&quot; /JWT_HEADER=&quot;[DOCUMENT_SERVER_JWT_HEADER]&quot; /DB_HOST=&quot;[PS_DB_HOST]&quot; /DB_USER=&quot;[PS_DB_USER]&quot; /DB_PWD=&quot;[PS_DB_PWD]&quot; /DB_NAME=&quot;[PS_DB_NAME]&quot; /LOG" NoUiComLine="/VERYSILENT /norestart /DIR=&quot;[APPDIR]..\DocumentServer&quot; /DS_PORT=&quot;[DOCUMENT_SERVER_PORT]&quot; /JWT_ENABLED=&quot;[DOCUMENT_SERVER_JWT_ENABLED]&quot; /JWT_SECRET=&quot;[DOCUMENT_SERVER_JWT_SECRET]&quot; /JWT_HEADER=&quot;[DOCUMENT_SERVER_JWT_HEADER]&quot; /DB_HOST=&quot;[PS_DB_HOST]&quot; /DB_USER=&quot;[PS_DB_USER]&quot; /DB_PWD=&quot;[PS_DB_PWD]&quot; /DB_NAME=&quot;[PS_DB_NAME]&quot; /LOG" Options="fi=" TargetName="onlyoffice-documentserver.exe" Builds="DefaultBuild" Feature="DocumentServer" RepairComLine="/VERYSILENT /norestart /DIR=&quot;[APPDIR]..\DocumentServer&quot; /DS_PORT=&quot;[DOCUMENT_SERVER_PORT]&quot; /JWT_ENABLED=&quot;[DOCUMENT_SERVER_JWT_ENABLED]&quot; /JWT_SECRET=&quot;[DOCUMENT_SERVER_JWT_SECRET]&quot; /JWT_HEADER=&quot;[DOCUMENT_SERVER_JWT_HEADER]&quot; /DB_HOST=&quot;[PS_DB_HOST]&quot; /DB_USER=&quot;[PS_DB_USER]&quot; /DB_PWD=&quot;[PS_DB_PWD]&quot; /DB_NAME=&quot;[PS_DB_NAME]&quot; /LOG"/>
<ROW PrereqKey="EA5B60A5CAD4115A8386D017CC889B9" DisplayName="ASP.NET Core Runtime 7.0.3 x64" VersionMin="7.0" SetupFileUrl="https://download.visualstudio.microsoft.com/download/pr/d37efccc-2ba1-4fc9-a1ef-a8e1e77fb681/b9a20fc29ff05f18d81620ec88ade699/aspnetcore-runtime-7.0.3-win-x64.exe" Location="1" ExactSize="9562088" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" WinNT64Versions="Windows Vista x64, Windows Server 2008 x64, Windows 7 RTM x64, Windows Server 2008 R2 x64, Windows 8 x64, Windows Server 2012 x64, Windows 10 version 1507 x64, Windows 10 version 1511 x64" Operator="1" ComLine="/q /norestart" BasicUiComLine="/q /norestart" NoUiComLine="/q /norestart" Options="xym" MD5="a87c53a62579d43c6e20683ad686c991" TargetName="ASP.NET Core 7.0"/>
<ROW PrereqKey="Erlangv26.0x64" DisplayName="Erlang v26.0.2 x64" VersionMin="26.0.2" SetupFileUrl="https://github.com/erlang/otp/releases/download/OTP-26.0.2/otp_win64_26.0.2.exe" Location="1" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/S" BasicUiComLine="/S" NoUiComLine="/S" Options="yx" TargetName="Erlang v26.0 x64"/>
@ -1535,10 +1541,10 @@
<ROW PrereqKey="RequiredApplication" DisplayName="MySQL Connector/ODBC 8.0.33 x86" VersionMin="8.0.33" SetupFileUrl="https://cdn.mysql.com/Downloads/Connector-ODBC/8.0/mysql-connector-odbc-8.0.33-win32.msi" Location="1" ExactSize="0" Operator="1" ComLine="/quiet" BasicUiComLine="/quiet" NoUiComLine="/quiet" Options="ym" TargetName="MySQL Connector ODBC 8.0.33 x86"/>
<ROW PrereqKey="RequiredApplication_1" DisplayName="Node.js 18.16.1" VersionMin="18.16.0" SetupFileUrl="https://nodejs.org/dist/v18.16.1/node-v18.16.1-x64.msi" Location="1" ExactSize="0" Operator="0" ComLine="/quiet" BasicUiComLine="/quiet" NoUiComLine="/quiet" Options="my" TargetName="Node.js v18.16.1 x64"/>
<ROW PrereqKey="RequiredApplication_2" DisplayName="MySQL Installer Community 8.0.33 x86" VersionMin="1.6.6.0" SetupFileUrl="https://cdn.mysql.com/Downloads/MySQLInstaller/mysql-installer-community-8.0.33.0.msi" Location="1" ExactSize="0" Operator="1" ComLine="/quiet" BasicUiComLine="/quiet" NoUiComLine="/quiet" Options="y" TargetName="MySQL Installer Community 8.0.33 x86"/>
<ROW PrereqKey="RequiredApplication_4" DisplayName="Elasticsearch v7.10.0 x64" VersionMin="7.10.0" SetupFileUrl="https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.10.0.msi" Location="1" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/quiet" BasicUiComLine="/quiet" NoUiComLine="/quiet" Options="y" TargetName="Elasticsearch v7.10.0 x64"/>
<ROW PrereqKey="RequiredApplication_4" DisplayName="Elasticsearch v7.16.3 x64" VersionMin="7.16.3" SetupFileUrl="https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.16.3.msi" Location="1" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/quiet" BasicUiComLine="/quiet" NoUiComLine="/quiet" Options="y" TargetName="Elasticsearch v7.16.3 x64"/>
<ROW PrereqKey="RequiredApplication_5" DisplayName="RabbitMQ v3.12.1 x64" VersionMin="3.12" SetupFileUrl="https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.12.1/rabbitmq-server-3.12.1.exe" Location="1" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/S" BasicUiComLine="/S" NoUiComLine="/S" Options="yx" TargetName="RabbitMQ v3.12.1 x64"/>
<ROW PrereqKey="RequiredApplication_6" DisplayName="Redis 5.0.10 x64" VersionMin="5.0" SetupFileUrl="http://download.onlyoffice.com/install/windows/redist/Redis-x64-5.0.10.msi" Location="1" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/quiet ADD_INSTALLFOLDER_TO_PATH=1" BasicUiComLine="/quiet ADD_INSTALLFOLDER_TO_PATH=1" NoUiComLine="/quiet ADD_INSTALLFOLDER_TO_PATH=1" Options="yx" TargetName="Redis 5.0.10 x64"/>
<ATTRIBUTE name="PrereqsOrder" value="B96F93FA27E74B02866727AAE83982D0 F3520F64DA5998338D97129FAD2 EA5B60A5CAD4115A8386D017CC889B9 CA62D813A4E74FA2AAE86A7D7B7B1493 A918597FE054CCCB65ABDBA0AD8F63C C4FE6FD5B7C4D07B3A313E754A9A6A8 RequiredApplication RequiredApplication_2 MySQLInstallerRunn RequiredApplication_1 RequiredApplication_4 Erlangv26.0x64 RequiredApplication_5 RequiredApplication_6 FFmpegx64 PostgreSQL_ODBC PostgresSQL OpenResty DocumentServer"/>
<ATTRIBUTE name="PrereqsOrder" value="B96F93FA27E74B02866727AAE83982D0 F3520F64DA5998338D97129FAD2 EA5B60A5CAD4115A8386D017CC889B9 CA62D813A4E74FA2AAE86A7D7B7B1493 A918597FE054CCCB65ABDBA0AD8F63C C4FE6FD5B7C4D07B3A313E754A9A6A8 RequiredApplication RequiredApplication_2 MySQLInstallerRunn RequiredApplication_1 RequiredApplication_4 Erlangv26.0x64 RequiredApplication_5 RequiredApplication_6 FFmpegx64 Certbot PostgreSQL_ODBC PostgresSQL OpenResty DocumentServer"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.PreReqSearchComponent">
<ROW SearchKey="A918597FE054CCCB65ABDBA0AD8F63CSyst" Prereq="A918597FE054CCCB65ABDBA0AD8F63C" SearchType="0" SearchString="[SystemFolder]vcruntime140.dll" VerMin="14.26.28720" Order="2" Property="PreReqSearch_A918597FE054CCCB65ABDB"/>
@ -1555,8 +1561,9 @@
<ROW SearchKey="SystemFolderfile.dll_1" Prereq="RequiredApplication_1" SearchType="4" SearchString="{47C07A3A-42EF-4213-A85D-8F5A59077C28}" VerMin="18.16.0" Order="1" Property="PreReqSearch_1"/>
<ROW SearchKey="SystemFolderfile.dll_2" Prereq="RequiredApplication_2" SearchType="4" SearchString="{18B94B70-06F1-4AC0-B308-37280DB868C2}" VerMin="1.6.6.0" Order="1" Property="PreReqSearch_2"/>
<ROW SearchKey="SystemFolderfile.dll_3" Prereq="OpenResty" SearchType="4" SearchString="{264FA774-91E5-4854-8010-4AB58CA830BD}" VerMin="1.21.4.2" Order="1" Property="PreReqSearch_8"/>
<ROW SearchKey="SystemFolderfile.dll_4" Prereq="Certbot" SearchType="2" SearchString="HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Certbot\DisplayVersion" VerMin="2.6.0" Order="1" Property="PreReqSearch_10"/>
<ROW SearchKey="UpgradeCode" Prereq="PostgreSQL_ODBC" SearchType="4" SearchString="{BBD29DF5-89F6-4B8B-BDC9-C3EA3A4AFDBB}" VerMin="15.0" Order="1" Property="PreReqSearch_14"/>
<ROW SearchKey="UpgradeCode_1" Prereq="RequiredApplication_4" SearchType="4" SearchString="{DAAA2CBA-A1ED-4F29-AFBF-5478617B00F6}" VerMin="7.10.0" Order="2" Property="PreReqSearch_7"/>
<ROW SearchKey="UpgradeCode_1" Prereq="RequiredApplication_4" SearchType="4" SearchString="{DAAA2CBA-A1ED-4F29-AFBF-5478617B00F6}" VerMin="7.16.3" Order="2" Property="PreReqSearch_7"/>
<ROW SearchKey="UpgradeCode_3" Prereq="RequiredApplication_6" SearchType="4" SearchString="{05410198-7212-4FC4-B7C8-AFEFC3DA0FBC}" VerMin="5.0.10" Order="2" Property="PreReqSearch_12"/>
<ROW SearchKey="Version" Prereq="MySQLInstallerRunn" SearchType="2" SearchString="HKLM\SOFTWARE\MySQL AB\MySQL Server 5.7\Version" Order="1" Property="PreReqSearch_4"/>
<ROW SearchKey="Version_1" Prereq="MySQLInstallerRunn" SearchType="2" SearchString="HKLM\SOFTWARE\MySQL AB\MySQL Server 8.0\Version" Order="2" Property="PreReqSearch_5"/>
@ -1572,17 +1579,22 @@
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.TxtUpdateComponent">
<ROW Name="ReplaceAppDir" TxtUpdateSet="xml" FindPattern="{APPDIR}" ReplacePattern="[APPDIR]" Options="2" Order="0" FileEncoding="-1"/>
<ROW Name="ReplaceAppDir1" TxtUpdateSet="YourFile.txt_5" FindPattern="{APPDIR}" ReplacePattern="[APPDIR]" Options="2" Order="0" FileEncoding="-1"/>
<ROW Name="ReplaceWinVol" TxtUpdateSet="xml" FindPattern="{WindowsVolume}" ReplacePattern="[WindowsVolume]" Options="2" Order="1" FileEncoding="-1"/>
<ROW Name="ReplaceInclude" TxtUpdateSet="YourFile.txt" FindPattern="/etc/nginx/includes" ReplacePattern="includes" Options="2" Order="0" FileEncoding="-1"/>
<ROW Name="ReplaceRoot" TxtUpdateSet="YourFile.txt_1" FindPattern="/var/www/client" ReplacePattern="&quot;[APPDIR]client&quot;" Options="2" Order="0" FileEncoding="-1"/>
<ROW Name="ReplaceRoot" TxtUpdateSet="YourFile.txt_2" FindPattern="/var/www/public/" ReplacePattern="&quot;[APPDIR]public/&quot;" Options="2" Order="0" FileEncoding="-1"/>
<ROW Name="ReplaceDsProxyPass" TxtUpdateSet="YourFile.txt" FindPattern="proxy_pass .*;" ReplacePattern="proxy_pass http://[DOCUMENT_SERVER_HOST]:[DOCUMENT_SERVER_PORT];" Options="19" Order="1" FileEncoding="-1"/>
<ROW Name="ReplaceListen" TxtUpdateSet="YourFile.txt" FindPattern="listen.*;" ReplacePattern="listen [APP_PORT];" Options="19" Order="2" FileEncoding="-1"/>
<ROW Name="ReplaceRouter" TxtUpdateSet="YourFile.txt_3" FindPattern="$router_host" ReplacePattern="127.0.0.1" Options="2" Order="0" FileEncoding="-1"/>
<ROW Name="ReplaceRouter1" TxtUpdateSet="YourFile.txt_4" FindPattern="$router_host" ReplacePattern="127.0.0.1" Options="2" Order="0" FileEncoding="-1"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.TxtUpdateSetComponent">
<ROW Key="YourFile.txt" Component="conf" FileName="onlyoffice.conf" Directory="conf_Dir" Options="17"/>
<ROW Key="YourFile.txt_1" Component="conf" FileName="onlyoffice-client.conf" Directory="conf_Dir" Options="17"/>
<ROW Key="YourFile.txt_2" Component="includes" FileName="onlyoffice-public.conf" Directory="includes_Dir" Options="17"/>
<ROW Key="YourFile.txt_3" Component="conf" FileName="onlyoffice-proxy.conf" Directory="conf_Dir" Options="17"/>
<ROW Key="YourFile.txt_4" Component="conf" FileName="onlyoffice-proxy-ssl.conf.tmpl" Directory="conf_Dir" Options="17"/>
<ROW Key="YourFile.txt_5" Component="includes" FileName="letsencrypt.conf" Directory="includes_Dir" Options="17"/>
<ROW Key="xml" Component="tools" FileName="*.xml" Directory="tools_Dir" Options="17"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.XmlAttributeComponent">

View File

@ -4,6 +4,7 @@
\pard\sa200\sl276\slmult1\f0\fs20\lang9 On the next step, you will have to review a list of components and applications provided by third parties. Ascensio System SIA is not associated with those third parties and can grant you no rights to use their software. To continue the installation of ONLYOFFICE DocSpace Enterprise, you will need to install the components listed below by reading and accepting their respective license terms if some of these components have not already been installed on your computer:\par
\pard{\pntext\f1\'B7\tab}{\*\pn\pnlvlblt\pnf1\pnindent0{\pntxtb\'B7}}\fi-360\li720\sa200\sl276\slmult1 .NET/C# RabbitMQ client library. It is distributed dual-licensed under the Apache License v2 and the Mozilla Public License v1.1 that can be found here: {{\field{\*\fldinst{HYPERLINK http://www.apache.org/licenses/LICENSE-2.0 }}{\fldrslt{http://www.apache.org/licenses/LICENSE-2.0\ul0\cf0}}}}\f0\fs20 {{\field{\*\fldinst{HYPERLINK https://www.rabbitmq.com/mpl.html }}{\fldrslt{https://www.rabbitmq.com/mpl.html\ul0\cf0}}}}\f0\fs20\par
{\pntext\f1\'B7\tab}Certbot. It is distributed under the following license: {{\field{\*\fldinst{HYPERLINK https://github.com/certbot/certbot/blob/master/LICENSE.txt }}{\fldrslt{https://github.com/certbot/certbot/blob/master/LICENSE.txt\ul0\cf0}}}}\f0\fs20 .\par
{\pntext\f1\'B7\tab}Elasticsearch. It is distributed under the Apache License v2 license that can be found here: {{\field{\*\fldinst{HYPERLINK http://www.apache.org/licenses/LICENSE-2.0 }}{\fldrslt{http://www.apache.org/licenses/LICENSE-2.0\ul0\cf0}}}}\f0\fs20 .\par
{\pntext\f1\'B7\tab}Erlang. It is distributed under the ERLANG PUBLIC LICENSE Version 1.1 license that can be found here: {{\field{\*\fldinst{HYPERLINK https://www.erlang.org/EPLICENSE }}{\fldrslt{https://www.erlang.org/EPLICENSE\ul0\cf0}}}}\f0\fs20 .\par
{\pntext\f1\'B7\tab}FFmpeg. It is distributed under the following license: {{\field{\*\fldinst{HYPERLINK https://github.com/rvs/ffmpeg/blob/master/LICENSE }}{\fldrslt{https://github.com/rvs/ffmpeg/blob/master/LICENSE\ul0\cf0}}}}\f0\fs20 .\par

View File

@ -4,6 +4,7 @@
\pard\sa200\sl276\slmult1\f0\fs20\lang9 On the next step, you will have to review a list of components and applications provided by third parties. Ascensio System SIA is not associated with those third parties and can grant you no rights to use their software. To continue the installation of ONLYOFFICE DocSpace Community, you will need to install the components listed below by reading and accepting their respective license terms if some of these components have not already been installed on your computer:\par
\pard{\pntext\f1\'B7\tab}{\*\pn\pnlvlblt\pnf1\pnindent0{\pntxtb\'B7}}\fi-360\li720\sa200\sl276\slmult1 .NET/C# RabbitMQ client library. It is distributed dual-licensed under the Apache License v2 and the Mozilla Public License v1.1 that can be found here: {{\field{\*\fldinst{HYPERLINK http://www.apache.org/licenses/LICENSE-2.0 }}{\fldrslt{http://www.apache.org/licenses/LICENSE-2.0\ul0\cf0}}}}\f0\fs20 {{\field{\*\fldinst{HYPERLINK https://www.rabbitmq.com/mpl.html }}{\fldrslt{https://www.rabbitmq.com/mpl.html\ul0\cf0}}}}\f0\fs20\par
{\pntext\f1\'B7\tab}Certbot. It is distributed under the following license: {{\field{\*\fldinst{HYPERLINK https://github.com/certbot/certbot/blob/master/LICENSE.txt }}{\fldrslt{https://github.com/certbot/certbot/blob/master/LICENSE.txt\ul0\cf0}}}}\f0\fs20 .\par
{\pntext\f1\'B7\tab}Elasticsearch. It is distributed under the Apache License v2 license that can be found here: {{\field{\*\fldinst{HYPERLINK http://www.apache.org/licenses/LICENSE-2.0 }}{\fldrslt{http://www.apache.org/licenses/LICENSE-2.0\ul0\cf0}}}}\f0\fs20 .\par
{\pntext\f1\'B7\tab}Erlang. It is distributed under the ERLANG PUBLIC LICENSE Version 1.1 license that can be found here: {{\field{\*\fldinst{HYPERLINK https://www.erlang.org/EPLICENSE }}{\fldrslt{https://www.erlang.org/EPLICENSE\ul0\cf0}}}}\f0\fs20 .\par
{\pntext\f1\'B7\tab}FFmpeg. It is distributed under the following license: {{\field{\*\fldinst{HYPERLINK https://github.com/rvs/ffmpeg/blob/master/LICENSE }}{\fldrslt{https://github.com/rvs/ffmpeg/blob/master/LICENSE\ul0\cf0}}}}\f0\fs20 .\par

View File

@ -8,6 +8,7 @@ md build\install\win\OpenResty\tools
md build\install\win\Files\tools
md build\install\win\Files\Logs
md build\install\win\Files\Data
md build\install\win\Files\sbin
md build\install\win\Files\products\ASC.Files\server\temp
md build\install\win\Files\products\ASC.People\server\temp
md build\install\win\Files\services\ASC.Data.Backup\service\temp
@ -30,8 +31,18 @@ copy build\install\win\tools\DocEditor.xml "build\install\win\Files\tools\DocEdi
copy build\install\win\WinSW3.0.0.exe "build\install\win\Files\tools\Login.exe" /y
copy build\install\win\tools\Login.xml "build\install\win\Files\tools\Login.xml" /y
copy "build\install\win\nginx.conf" "build\install\win\Files\nginx\conf\nginx.conf" /y
copy "build\install\docker\config\nginx\onlyoffice-proxy.conf" "build\install\win\Files\nginx\conf\onlyoffice-proxy.conf" /y
copy "build\install\docker\config\nginx\onlyoffice-proxy-ssl.conf" "build\install\win\Files\nginx\conf\onlyoffice-proxy-ssl.conf.tmpl" /y
copy "build\install\docker\config\nginx\letsencrypt.conf" "build\install\win\Files\nginx\conf\includes\letsencrypt.conf" /y
copy "build\install\win\sbin\docspace-ssl-setup.ps1" "build\install\win\Files\sbin\docspace-ssl-setup.ps1" /y
rmdir build\install\win\publish /s /q
REM echo ######## SSL configs ########
%sed% -i "s/the_host/host/g" build\install\win\Files\nginx\conf\onlyoffice-proxy.conf build\install\win\Files\nginx\conf\onlyoffice-proxy-ssl.conf.tmpl
%sed% -i "s/the_scheme/scheme/g" build\install\win\Files\nginx\conf\onlyoffice-proxy.conf build\install\win\Files\nginx\conf\onlyoffice-proxy-ssl.conf.tmpl
%sed% -i "s/ssl_dhparam \/etc\/ssl\/certs\/dhparam.pem;/#ssl_dhparam \/etc\/ssl\/certs\/dhparam.pem;/" build\install\win\Files\nginx\conf\onlyoffice-proxy-ssl.conf.tmpl
%sed% -i "s_\(.*root\).*;_\1 \"{APPDIR}letsencrypt\";_g" -i build\install\win\Files\nginx\conf\includes\letsencrypt.conf
REM echo ######## Delete test and dev configs ########
del /f /q build\install\win\Files\config\*.test.json
del /f /q build\install\win\Files\config\*.dev.json
@ -41,6 +52,8 @@ del /f /q build\install\win\Files\config\*.dev.json
%sed% "s_\(\"logLevel\":\).*_\1 \"warning\"_g" -i build\install\win\Files\config\appsettings.services.json
%sed% "/\"debug-info\": {/,/}/ s/\(\"enabled\": \)\".*\"/\1\"false\"/" -i build\install\win\Files\config\appsettings.json
%sed% "s_\(\"samesite\":\).*,_\1 \"None\",_g" -i build\install\win\Files\config\appsettings.json
::redirectUrl value replacement
%sed% "s/teamlab.info/onlyoffice.com/g" -i build\install\win\Files\config/autofac.consumers.json

View File

@ -155,8 +155,8 @@ $enterprise_prerequisites = @(
@{
download_allways = $false;
name = "elasticsearch-7.10.0.msi";
link = "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.10.0.msi";
name = "elasticsearch-7.16.3.msi";
link = "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.16.3.msi";
}
@{
@ -194,6 +194,12 @@ $enterprise_prerequisites = @(
name = "postgresql-${psql_version}-1-windows-x64.exe";
link = "https://get.enterprisedb.com/postgresql/postgresql-${psql_version}-1-windows-x64.exe"
}
@{
download_allways = $false;
name = "certbot-2.6.0.exe";
link = "https://github.com/certbot/certbot/releases/download/v2.6.0/certbot-beta-installer-win_amd64_signed.exe"
}
)
DownloadComponents $prerequisites $path_prereq

View File

@ -0,0 +1,101 @@
# runas administrator
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
exit
}
function Test-RegistryValue($RegistryKey, $RegistryName)
{
$exists = Get-ItemProperty -Path "$RegistryKey" -Name "$RegistryName" -ErrorAction SilentlyContinue
if (($exists -ne $null) -and ($exists.Length -ne 0)) { return $true }
return $false
}
$certbot_path = if ((Test-RegistryValue "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Certbot" "InstallLocation") -eq $true )
{
(Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Certbot" -ErrorAction Stop).InstallLocation
}
elseif ((Test-RegistryValue "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Certbot" "InstallLocation") -eq $true )
{
(Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Certbot" -ErrorAction Stop).InstallLocation
}
if ( -not $certbot_path )
{
Write-Output " Attention! Certbot is not installed on your computer. "
Write-Output " Certbot could be downloaded by this link 'https://github.com/certbot/certbot/releases/latest/download/certbot-beta-installer-win_amd64_signed.exe' "
exit
}
if ( $args.Count -ge 2 )
{
$letsencrypt_root_dir = "$env:SystemDrive\Certbot\live"
$app = Resolve-Path -Path ".\..\"
$root_dir = "${app}\letsencrypt"
$nginx_conf_dir = "$env:SystemDrive\OpenResty\conf"
$nginx_conf = "onlyoffice-proxy.conf"
$nginx_tmpl = "onlyoffice-proxy-ssl.conf.tmpl"
$proxy_service = "OpenResty"
$appsettings_config_path = "${app}\config\appsettings.production.json"
if ($args[0] -eq "-f") {
$ssl_cert = $args[1]
$ssl_key = $args[2]
}
else {
$letsencrypt_mail = $args[0]
$letsencrypt_domain = $args[1]
[void](New-Item -ItemType "directory" -Path "${root_dir}\Logs" -Force)
"certbot certonly --expand --webroot -w `"${root_dir}`" --noninteractive --agree-tos --email ${letsencrypt_mail} -d ${letsencrypt_domain}" > "${app}\letsencrypt\Logs\le-start.log"
cmd.exe /c "certbot certonly --expand --webroot -w `"${root_dir}`" --noninteractive --agree-tos --email ${letsencrypt_mail} -d ${letsencrypt_domain}" > "${app}\letsencrypt\Logs\le-new.log"
pushd "${letsencrypt_root_dir}\${letsencrypt_domain}"
$ssl_cert = (Resolve-Path -Path (Get-Item "${letsencrypt_root_dir}\${letsencrypt_domain}\fullchain.pem").Target).ToString().Replace('\', '/')
$ssl_key = (Resolve-Path -Path (Get-Item "${letsencrypt_root_dir}\${letsencrypt_domain}\privkey.pem").Target).ToString().Replace('\', '/')
popd
}
if ( [System.IO.File]::Exists($ssl_cert) -and [System.IO.File]::Exists($ssl_key) -and [System.IO.File]::Exists("${nginx_conf_dir}\${nginx_tmpl}"))
{
Copy-Item "${nginx_conf_dir}\${nginx_tmpl}" -Destination "${nginx_conf_dir}\${nginx_conf}"
((Get-Content -Path "${nginx_conf_dir}\${nginx_conf}" -Raw) -replace '/usr/local/share/ca-certificates/tls.crt', $ssl_cert) | Set-Content -Path "${nginx_conf_dir}\${nginx_conf}"
((Get-Content -Path "${nginx_conf_dir}\${nginx_conf}" -Raw) -replace '/etc/ssl/private/tls.key', $ssl_key) | Set-Content -Path "${nginx_conf_dir}\${nginx_conf}"
if ($letsencrypt_domain)
{
$acl = Get-Acl -Path "$env:SystemDrive\Certbot\archive\${letsencrypt_domain}"
$acl.SetSecurityDescriptorSddlForm('O:LAG:S-1-5-21-4011186057-2202358572-2315966083-513D:PAI(A;;0x1200a9;;;WD)(A;;FA;;;SY)(A;OI;0x1200a9;;;LS)(A;;FA;;;BA)(A;;FA;;;LA)')
Set-Acl -Path $acl.path -ACLObject $acl
}
}
Restart-Service -Name $proxy_service
"certbot renew >> `"${app}\letsencrypt\Logs\le-renew.log`"" > "${app}\letsencrypt\letsencrypt_cron.bat"
"net stop $proxy_service" >> "${app}\letsencrypt\letsencrypt_cron.bat"
"net start $proxy_service" >> "${app}\letsencrypt\letsencrypt_cron.bat"
$day = (Get-Date -Format "dddd").ToUpper().SubString(0, 3)
$time = Get-Date -Format "HH:mm"
cmd.exe /c "SCHTASKS /F /CREATE /SC WEEKLY /D $day /TN `"Certbot renew`" /TR `"${app}\letsencrypt\letsencrypt_cron.bat`" /ST $time"
}
else
{
Write-Output " This script provided to automatically get Let's Encrypt SSL Certificates for DocSpace "
Write-Output " usage: "
Write-Output " docspace-ssl-setup.ps1 EMAIL DOMAIN "
Write-Output " EMAIL Email used for registration and recovery contact. Use "
Write-Output " comma to register multiple emails, ex: "
Write-Output " u1@example.com,u2@example.com. "
Write-Output " DOMAIN Domain name to apply "
Write-Output " "
Write-Output " Using your own certificates via the -f parameter: "
Write-Output " usage: "
Write-Output " docspace-ssl-setup.ps1 -f CERTIFICATE PRIVATEKEY "
Write-Output " CERTIFICATE Path to the certificate file for the domain."
Write-Output " PRIVATEKEY Path to the private key file for the certificate."
}

View File

@ -1,5 +1,5 @@
<service>
<id>ASC.DocEditor</id>
<id>DocSpace.DocEditor</id>
<name>ONLYOFFICE DocSpace DocEditor</name>
<description>ONLYOFFICE DocSpace DocEditor</description>
<priority>RealTime</priority>

View File

@ -1,5 +1,5 @@
<service>
<id>ASC.Login</id>
<id>DocSpace.Login</id>
<name>ONLYOFFICE DocSpace Login</name>
<description>ONLYOFFICE DocSpace Login</description>
<priority>RealTime</priority>

View File

@ -1,5 +1,5 @@
<service>
<id>ASC.Socket.IO</id>
<id>DocSpace.Socket.IO</id>
<name>ONLYOFFICE DocSpace Socket.IO</name>
<description>ONLYOFFICE DocSpace Socket.IO</description>
<priority>RealTime</priority>

View File

@ -1,5 +1,5 @@
<service>
<id>ASC.SsoAuth</id>
<id>DocSpace.SsoAuth.Svc</id>
<name>ONLYOFFICE DocSpace SsoAuth.Svc</name>
<description>ONLYOFFICE DocSpace ASC.SsoAuth.Svc</description>
<priority>RealTime</priority>

View File

@ -227,13 +227,13 @@ Function ElasticSearchSetup
Set Shell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
APP_INDEX_DIR = Session.Property("APPDIR") & "Data\Index\v7.10.0\"
APP_INDEX_DIR = Session.Property("APPDIR") & "Data\Index\v7.16.3\"
If Not fso.FolderExists(APP_INDEX_DIR) Then
Session.Property("NEED_REINDEX_ELASTICSEARCH") = "TRUE"
End If
Call Shell.Run("%COMSPEC% /c mkdir """ & Session.Property("APPDIR") & "Data\Index\v7.10.0\""",0,true)
Call Shell.Run("%COMSPEC% /c mkdir """ & Session.Property("APPDIR") & "Data\Index\v7.16.3\""",0,true)
Call Shell.Run("%COMSPEC% /c mkdir """ & Session.Property("APPDIR") & "Logs\""",0,true)
Set objFile = objFSO.OpenTextFile(Session.Property("CommonAppDataFolder") & "Elastic\Elasticsearch\config\elasticsearch.yml", ForReading)
@ -285,11 +285,18 @@ Function ElasticSearchSetup
End if
oRE.Pattern = "path.data:.*"
fileContent = oRE.Replace(fileContent, "path.data: " & Session.Property("APPDIR") & "Data\Index\v7.10.0\")
fileContent = oRE.Replace(fileContent, "path.data: " & Session.Property("APPDIR") & "Data\Index\v7.16.3\")
oRE.Pattern = "path.logs:.*"
fileContent = oRE.Replace(fileContent, "path.logs: " & Session.Property("APPDIR") & "Logs\")
If InStrRev(fileContent, "ingest.geoip.downloader.enabled") = 0 Then
fileContent = fileContent & Chr(13) & Chr(10) & "ingest.geoip.downloader.enabled: false"
Else
oRE.Pattern = "ingest.geoip.downloader.enabled.*"
fileContent = oRE.Replace(fileContent, "ingest.geoip.downloader.enabled: false")
End if
Call WriteToLog("ElasticSearchSetup: New config:" & fileContent)
Call WriteToLog("ElasticSearchSetup: CommonAppDataFolder :" & Session.Property("CommonAppDataFolder") & "Elastic\Elasticsearch\data")
@ -324,6 +331,13 @@ Function ElasticSearchSetup
fileContent = fileContent & Chr(13) & Chr(10) & "-Xmx4g"
End if
If InStrRev(fileContent, "-Dlog4j2.formatMsgNoLookups") = 0 Then
fileContent = fileContent & Chr(13) & Chr(10) & "-Dlog4j2.formatMsgNoLookups=true"
Else
oRE.Pattern = "-Dlog4j2.formatMsgNoLookups.*"
fileContent = oRE.Replace(fileContent, "-Dlog4j2.formatMsgNoLookups=true")
End if
Set objFile = objFSO.OpenTextFile(Session.Property("CommonAppDataFolder") & "Elastic\Elasticsearch\config\jvm.options", ForWriting)
objFile.WriteLine fileContent
@ -341,8 +355,8 @@ Function ElasticSearchInstallPlugin
Set Shell = CreateObject("WScript.Shell")
ShellInstallCommand = """C:\Program Files\Elastic\Elasticsearch\7.10.0\bin\elasticsearch-plugin""" & " install -b -s ingest-attachment"""
ShellRemoveCommand = """C:\Program Files\Elastic\Elasticsearch\7.10.0\bin\elasticsearch-plugin""" & " remove -s ingest-attachment"""
ShellInstallCommand = """C:\Program Files\Elastic\Elasticsearch\7.16.3\bin\elasticsearch-plugin""" & " install -b -s ingest-attachment"""
ShellRemoveCommand = """C:\Program Files\Elastic\Elasticsearch\7.16.3\bin\elasticsearch-plugin""" & " remove -s ingest-attachment"""
Call Shell.Run("cmd /C " & """" & ShellRemoveCommand & """",0,true)
Call Shell.Run("cmd /C " & """" & ShellInstallCommand & """",0,true)

View File

@ -369,4 +369,9 @@ class CachedTenantService : ITenantService
_cacheNotifySettings.Publish(new TenantSetting { Key = cacheKey }, CacheNotifyAction.Remove);
}
public IEnumerable<Tenant> GetTenantsWithCsp()
{
return _service.GetTenantsWithCsp();
}
}

View File

@ -180,7 +180,7 @@ public class UserManager
return await users.ToArrayAsync();
}
public Task<int> GetUsersCountAsync(
bool isDocSpaceAdmin,
EmployeeStatus? employeeStatus,
@ -360,17 +360,23 @@ public class UserManager
return findUsers.ToArray();
}
public async Task<UserInfo> UpdateUserInfoAsync(UserInfo u)
public async Task<UserInfo> UpdateUserInfoAsync(UserInfo u, bool afterInvite = false)
{
if (IsSystemUser(u.Id))
{
return SystemUsers[u.Id];
}
await _permissionContext.DemandPermissionsAsync(new UserSecurityProvider(u.Id), Constants.Action_EditUser);
if (afterInvite)
{
await _permissionContext.DemandPermissionsAsync(new UserSecurityProvider(u.Id, await this.GetUserTypeAsync(u.Id)), Constants.Action_AddRemoveUser);
}
else
{
await _permissionContext.DemandPermissionsAsync(new UserSecurityProvider(u.Id), Constants.Action_EditUser);
}
var tenant = await _tenantManager.GetCurrentTenantAsync();
if (u.Status == EmployeeStatus.Terminated && u.Id == tenant.OwnerId)
{
throw new InvalidOperationException("Can not disable tenant owner.");
@ -559,8 +565,8 @@ public class UserManager
new Uri(_cache.Get<string>("REWRITE_URL" + tenant.Id)).ToString() : tenant.GetTenantDomain(_coreSettings);
var davUsersEmails = await GetDavUserEmailsAsync();
var requestUrlBook = _cardDavAddressbook.GetRadicaleUrl(myUri, delUser.Email.ToLower(), true, true);
if(rootAuthorization != null)
if (rootAuthorization != null)
{
var addBookCollection = await _cardDavAddressbook.GetCollection(requestUrlBook, userAuthorization, myUri.ToString());
if (addBookCollection.Completed && addBookCollection.StatusCode != 404)

View File

@ -31,6 +31,7 @@ public interface ITenantService
{
Task<byte[]> GetTenantSettingsAsync(int tenant, string key);
byte[] GetTenantSettings(int tenant, string key);
IEnumerable<Tenant> GetTenantsWithCsp();
Task<IEnumerable<Tenant>> GetTenantsAsync(DateTime from, bool active = true);
Task<IEnumerable<Tenant>> GetTenantsAsync(List<int> ids);
Task<IEnumerable<Tenant>> GetTenantsAsync(string login, string passwordHash);

View File

@ -32,6 +32,7 @@ public class DbTenantService : ITenantService
private readonly TenantDomainValidator _tenantDomainValidator;
private readonly IDbContextFactory<TenantDbContext> _dbContextFactory;
private readonly IDbContextFactory<UserDbContext> _userDbContextFactory;
private readonly IDbContextFactory<WebstudioDbContext> _webstudioDbContext;
private readonly IMapper _mapper;
private readonly MachinePseudoKeys _machinePseudoKeys;
private List<string> _forbiddenDomains;
@ -41,13 +42,15 @@ public class DbTenantService : ITenantService
IDbContextFactory<UserDbContext> userDbContextFactory,
TenantDomainValidator tenantDomainValidator,
MachinePseudoKeys machinePseudoKeys,
IMapper mapper)
IMapper mapper,
IDbContextFactory<WebstudioDbContext> webstudioDbContext)
{
_dbContextFactory = dbContextFactory;
_userDbContextFactory = userDbContextFactory;
_tenantDomainValidator = tenantDomainValidator;
_machinePseudoKeys = machinePseudoKeys;
_mapper = mapper;
_webstudioDbContext = webstudioDbContext;
}
public async Task ValidateDomainAsync(string domain)
@ -75,6 +78,18 @@ public class DbTenantService : ITenantService
return await q.ProjectTo<Tenant>(_mapper.ConfigurationProvider).ToListAsync();
}
public IEnumerable<Tenant> GetTenantsWithCsp()
{
var cspSettingsId = new CspSettings().ID;
using var webstudioDbContext = _webstudioDbContext.CreateDbContext();
var q = webstudioDbContext.Tenants
.Join(webstudioDbContext.WebstudioSettings.DefaultIfEmpty(), r => r.Id, r => r.TenantId, (tenant, settings) => new { settings, tenant })
.Where(r => r.settings.Id == cspSettingsId)
.Select(r => r.tenant);
return q.ProjectTo<Tenant>(_mapper.ConfigurationProvider).ToList();
}
public async Task<IEnumerable<Tenant>> GetTenantsAsync(List<int> ids)
{
await using var tenantDbContext = _dbContextFactory.CreateDbContext();

View File

@ -83,7 +83,7 @@ public static class DbQuotaExtension
TenantId = -3,
Name = "startup",
Description = null,
Features = "free,total_size:2147483648,manager:3,room:12",
Features = "free,oauth,total_size:2147483648,manager:3,room:12",
Price = 0,
ProductId = null,
Visible = false

View File

@ -35,6 +35,6 @@ public class CspSettings : ISettings<CspSettings>
public CspSettings GetDefault()
{
return new CspSettings();
return new CspSettings() { Domains = new List<string>() };
}
}

View File

@ -56,7 +56,8 @@ public class StorageHandler
var auth = context.Request.Query[Constants.QueryAuth].FirstOrDefault() ?? "";
var storageExpire = storage.GetExpire(_domain);
if (_checkAuth && !securityContext.IsAuthenticated && !await SecureHelper.CheckSecureKeyHeader(header, path, emailValidationKeyProvider))
if (_checkAuth && !securityContext.IsAuthenticated && !await SecureHelper.CheckSecureKeyHeader(header, path, emailValidationKeyProvider)
|| _module == "backup" && !securityContext.IsAuthenticated)
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return;

View File

@ -32,6 +32,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.32.1" />
<PackageReference Include="TweetinviAPI" Version="5.0.4" />
</ItemGroup>
<ItemGroup>

View File

@ -42,16 +42,12 @@ public class ProviderManager
public static readonly List<string> AuthProviders = new List<string>
{
ProviderConstants.Google,
ProviderConstants.Facebook,
ProviderConstants.Twitter,
ProviderConstants.Zoom,
ProviderConstants.LinkedIn,
ProviderConstants.MailRu,
ProviderConstants.VK,
ProviderConstants.Yandex,
ProviderConstants.GosUslugi,
ProviderConstants.AppleId,
ProviderConstants.Facebook ,
ProviderConstants.Twitter,
ProviderConstants.Microsoft,
ProviderConstants.Zoom
ProviderConstants.AppleId
};
public static List<string> InviteExceptProviders = new List<string>

View File

@ -24,144 +24,144 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using System.Globalization;
//using System;
//using System.Collections.Generic;
//using System.Globalization;
//using System.Web;
using Tweetinvi;
using Tweetinvi.Auth;
using Tweetinvi.Parameters;
//using ASC.FederatedLogin.Profile;
namespace ASC.FederatedLogin.LoginProviders;
//using Newtonsoft.Json.Linq;
public class TwitterLoginProvider : BaseLoginProvider<TwitterLoginProvider>
{
public override string AccessTokenUrl { get { return "https://api.twitter.com/oauth/access_token"; } }
public override string RedirectUri { get { return this["twitterRedirectUrl"]; } }
public override string ClientID { get { return this["twitterKey"]; } }
public override string ClientSecret { get { return this["twitterSecret"]; } }
public override string CodeUrl { get { return "https://api.twitter.com/oauth/request_token"; } }
//using Tweetinvi;
//using Tweetinvi.Auth;
//using Tweetinvi.Parameters;
private static readonly IAuthenticationRequestStore _myAuthRequestStore = new LocalAuthenticationRequestStore();
//namespace ASC.FederatedLogin.LoginProviders
//{
// public class TwitterLoginProvider : BaseLoginProvider<TwitterLoginProvider>
// {
// public static string TwitterKey { get { return Instance.ClientID; } }
// public static string TwitterSecret { get { return Instance.ClientSecret; } }
// public static string TwitterDefaultAccessToken { get { return Instance["twitterAccessToken_Default"]; } }
// public static string TwitterAccessTokenSecret { get { return Instance["twitterAccessTokenSecret_Default"]; } }
public override bool IsEnabled
{
get
{
return !string.IsNullOrEmpty(ClientID) &&
!string.IsNullOrEmpty(ClientSecret);
}
}
// public override string AccessTokenUrl { get { return "https://api.twitter.com/oauth/access_token"; } }
// public override string RedirectUri { get { return this["twitterRedirectUrl"]; } }
// public override string ClientID { get { return this["twitterKey"]; } }
// public override string ClientSecret { get { return this["twitterSecret"]; } }
// public override string CodeUrl { get { return "https://api.twitter.com/oauth/request_token"; } }
public TwitterLoginProvider() { }
public TwitterLoginProvider(
OAuth20TokenHelper oAuth20TokenHelper,
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory,
Signature signature,
InstanceCrypto instanceCrypto,
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
: base(oAuth20TokenHelper, tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory, signature, instanceCrypto, name, order, props, additional)
{
}
// private static readonly IAuthenticationRequestStore _myAuthRequestStore = new LocalAuthenticationRequestStore();
// public override bool IsEnabled
// {
// get
// {
// return !string.IsNullOrEmpty(ClientID) &&
// !string.IsNullOrEmpty(ClientSecret);
// }
// }
public override LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params, IDictionary<string, string> additionalStateArgs)
{
if (!string.IsNullOrEmpty(context.Request.Query["denied"]))
{
return LoginProfile.FromError(Signature, InstanceCrypto, new Exception("Canceled at provider"));
}
// public TwitterLoginProvider() { }
// public TwitterLoginProvider(string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null) : base(name, order, props, additional) { }
var appClient = new TwitterClient(ClientID, ClientSecret);
// public override LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params)
// {
// if (!string.IsNullOrEmpty(context.Request["denied"]))
// {
// return LoginProfile.FromError(new Exception("Canceled at provider"));
// }
if (string.IsNullOrEmpty(context.Request.Query["oauth_token"]))
{
var callbackAddress = new UriBuilder(RedirectUri)
{
Query = "state=" + HttpUtility.UrlEncode(context.Request.Url().AbsoluteUri)
};
// var appClient = new TwitterClient(TwitterKey, TwitterSecret);
var authenticationRequestId = Guid.NewGuid().ToString();
// if (string.IsNullOrEmpty(context.Request["oauth_token"]))
// {
// var callbackAddress = new UriBuilder(RedirectUri)
// {
// Query = "state=" + HttpUtility.UrlEncode(context.Request.Url().AbsoluteUri)
// };
// Add the user identifier as a query parameters that will be received by `ValidateTwitterAuth`
var redirectURL = _myAuthRequestStore.AppendAuthenticationRequestIdToCallbackUrl(callbackAddress.ToString(), authenticationRequestId);
// var authenticationRequestId = Guid.NewGuid().ToString();
// Initialize the authentication process
var authenticationRequestToken = appClient.Auth.RequestAuthenticationUrlAsync(redirectURL)
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
// // Add the user identifier as a query parameters that will be received by `ValidateTwitterAuth`
// var redirectURL = _myAuthRequestStore.AppendAuthenticationRequestIdToCallbackUrl(callbackAddress.ToString(), authenticationRequestId);
// Store the token information in the store
_myAuthRequestStore.AddAuthenticationTokenAsync(authenticationRequestId, authenticationRequestToken)
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
// // Initialize the authentication process
// var authenticationRequestToken = appClient.Auth.RequestAuthenticationUrlAsync(redirectURL)
// .ConfigureAwait(false)
// .GetAwaiter()
// .GetResult();
context.Response.Redirect(authenticationRequestToken.AuthorizationURL, true);
// // Store the token information in the store
// _myAuthRequestStore.AddAuthenticationTokenAsync(authenticationRequestId, authenticationRequestToken)
// .ConfigureAwait(false)
// .GetAwaiter()
// .GetResult();
return null;
}
// context.Response.Redirect(authenticationRequestToken.AuthorizationURL, true);
// Extract the information from the redirection url
var requestParameters = RequestCredentialsParameters.FromCallbackUrlAsync(context.Request.GetDisplayUrl(), _myAuthRequestStore).GetAwaiter().GetResult();
// Request Twitter to generate the credentials.
var userCreds = appClient.Auth.RequestCredentialsAsync(requestParameters)
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
// return null;
// }
// Congratulations the user is now authenticated!
var userClient = new TwitterClient(userCreds);
// // Extract the information from the redirection url
// var requestParameters = RequestCredentialsParameters.FromCallbackUrlAsync(context.Request.RawUrl, _myAuthRequestStore).GetAwaiter().GetResult();
// // Request Twitter to generate the credentials.
// var userCreds = appClient.Auth.RequestCredentialsAsync(requestParameters)
// .ConfigureAwait(false)
// .GetAwaiter()
// .GetResult();
var user = userClient.Users.GetAuthenticatedUserAsync()
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
// // Congratulations the user is now authenticated!
// var userClient = new TwitterClient(userCreds);
var userSettings = userClient.AccountSettings.GetAccountSettingsAsync()
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
// var user = userClient.Users.GetAuthenticatedUserAsync()
// .ConfigureAwait(false)
// .GetAwaiter()
// .GetResult();
return user == null
? null
: new LoginProfile(Signature, InstanceCrypto)
{
Name = user.Name,
DisplayName = user.ScreenName,
Avatar = user.ProfileImageUrl,
Locale = userSettings.Language.ToString(),
Id = user.Id.ToString(CultureInfo.InvariantCulture),
Provider = ProviderConstants.Twitter
};
// var userSettings = userClient.AccountSettings.GetAccountSettingsAsync()
// .ConfigureAwait(false)
// .GetAwaiter()
// .GetResult();
}
// return user == null
// ? null
// : new LoginProfile
// {
// Name = user.Name,
// DisplayName = user.ScreenName,
// Avatar = user.ProfileImageUrl,
// Locale = userSettings.Language.ToString(),
// Id = user.Id.ToString(CultureInfo.InvariantCulture),
// Provider = ProviderConstants.Twitter
// };
protected override OAuth20Token Auth(HttpContext context, string scopes, out bool redirect, IDictionary<string, string> additionalArgs = null, IDictionary<string, string> additionalStateArgs = null)
{
throw new NotImplementedException();
}
// }
public override LoginProfile GetLoginProfile(string accessToken)
{
throw new NotImplementedException();
}
// protected override OAuth20Token Auth(HttpContext context, string scopes, Dictionary<string, string> additional = null)
// {
// throw new NotImplementedException();
// }
internal LoginProfile ProfileFromTwitter(string twitterProfile)
{
var jProfile = JObject.Parse(twitterProfile);
if (jProfile == null) throw new Exception("Failed to correctly process the response");
// public override LoginProfile GetLoginProfile(string accessToken)
// {
// throw new NotImplementedException();
// }
// internal static LoginProfile ProfileFromTwitter(string twitterProfile)
// {
// var jProfile = JObject.Parse(twitterProfile);
// if (jProfile == null) throw new Exception("Failed to correctly process the response");
// return new LoginProfile
// {
// DisplayName = jProfile.Value<string>("name"),
// Locale = jProfile.Value<string>("lang"),
// Id = jProfile.Value<string>("id"),
// Provider = ProviderConstants.Twitter
// };
// }
// }
//}
return new LoginProfile(Signature, InstanceCrypto)
{
DisplayName = jProfile.Value<string>("name"),
Locale = jProfile.Value<string>("lang"),
Id = jProfile.Value<string>("id"),
Provider = ProviderConstants.Twitter
};
}
}

View File

@ -409,6 +409,28 @@
}
]
},
"csp":{
"default": {
"def": ["'self'", "data:"],
"script": ["'self'", "'unsafe-inline'", "'unsafe-eval'"],
"style": ["'self'", "'unsafe-inline'"],
"img": ["'self'", "data:", "blob:"],
"frame": ["'self'"]
},
"zendesk":{
"def": ["*.zdassets.com", "*.zopim.com", "*.zendesk.com", "wss:" ],
"script": ["*.zdassets.com", "*.zopim.com","'unsafe-eval'"],
"img": ["*.zopim.io" ]
},
"firebase":{
"script": ["*.googleapis.com"],
"def": ["*.googleapis.com" ]
},
"oform":{
"img": ["*.onlyoffice.com"],
"def": ["*.onlyoffice.com" ]
}
},
"logocolors":[
{"r":255, "g":102, "b":128},
{"r":255, "g":143, "b":64},

View File

@ -10,11 +10,11 @@
"type": "ASC.FederatedLogin.LoginProviders.AppleIdLoginProvider, ASC.FederatedLogin"
},
{
"key": "appleID",
"key": "appleid",
"type": "ASC.Core.Common.Configuration.Consumer, ASC.Core.Common"
},
{
"key": "appleID",
"key": "appleid",
"type": "ASC.FederatedLogin.LoginProviders.AppleIdLoginProvider, ASC.FederatedLogin"
}
],
@ -182,6 +182,37 @@
"facebookRedirectUrl" : "https://service.teamlab.info/oauth2.aspx"
}
}
},
{
"type": "ASC.FederatedLogin.LoginProviders.TwitterLoginProvider, ASC.FederatedLogin",
"services": [
{
"type": "ASC.Core.Common.Configuration.Consumer, ASC.Core.Common"
},
{
"type": "ASC.FederatedLogin.LoginProviders.TwitterLoginProvider, ASC.FederatedLogin"
},
{
"key": "twitter",
"type": "ASC.Core.Common.Configuration.Consumer, ASC.Core.Common"
},
{
"key": "twitter",
"type": "ASC.FederatedLogin.LoginProviders.TwitterLoginProvider, ASC.FederatedLogin"
}
],
"instanceScope": "perlifetimescope",
"parameters": {
"name": "twitter",
"order": "6",
"props": {
"twitterKey": "",
"twitterSecret": ""
},
"additional": {
"twitterRedirectUrl" : "https://service.teamlab.info/oauth2.aspx"
}
}
},
{
"type": "ASC.Web.Core.Jabber.FireBase, ASC.Web.Core",

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ASC.Migrations.MySql.SaaS.Migrations
{
/// <inheritdoc />
public partial class MigrationContext_Upgrade6 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "tenants_quota",
keyColumn: "tenant",
keyValue: -3,
column: "features",
value: "free,oauth,total_size:2147483648,manager:3,room:12");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "tenants_quota",
keyColumn: "tenant",
keyValue: -3,
column: "features",
value: "free,total_size:2147483648,manager:3,room:12");
}
}
}

View File

@ -724,7 +724,7 @@ namespace ASC.Migrations.MySql.SaaS.Migrations
new
{
TenantId = -3,
Features = "free,total_size:2147483648,manager:3,room:12",
Features = "free,oauth,total_size:2147483648,manager:3,room:12",
Name = "startup",
Price = 0m,
Visible = false

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "{{element}} köçür",
"TooltipElementsCopyMessage": "{{element}} elementlərini köçürmək",
"TooltipElementsMoveMessage": "{{element}} elementinin yerdəyişməsi",
"TrashEmptyDescription": "'Səbət' bölməsinə bütün silinmiş fayllar yerləşdirilirlər. Əgər onlar səhvən siliniblərsə, Siz onları bərpa edə bilərsiniz, və ya onları ömürlük silə bilərsiniz. Lütfən, nəzərə alın ki, 'Səbətdən' silinən fayllar bir də bərpa oluna bilməyəcəklər.",
"TrashEmptyDescription": "'Səbət' bölməsinə bütün silinmiş fayllar yerləşdirilirlər. Əgər onlar səhvən siliniblərsə, Siz onları bərpa edə bilərsiniz, və ya onları ömürlük silə bilərsiniz. 'Səbətdən' fayllar 30 gündən sonra avtomatik silinir. Lütfən, nəzərə alın ki, 'Səbətdən' silinən fayllar bir də bərpa oluna bilməyəcəklər.",
"TrashErasureWarning": "Zibil qutusundakı elementlər 30 gündən sonra avtomatik silinir.",
"UnarchivedRoomAction": "'{{name}}' otağı arxivdən çıxarıldı.",
"UnarchivedRoomsAction": "Otaqlar arxivdən çıxarıldı.",

View File

@ -5,8 +5,8 @@
"DeleteRoom": "На път сте да изтриете тази стая. Няма да можете да възстановите тези данни.",
"DeleteRooms": "На път сте да изтриете тези стаи. Няма да можете да ги възстановите.",
"MoveToTrashButton": "Премести в Кошчето",
"MoveToTrashFile": "На път сте да изтриете този файл? Моля, обърнете внимание, че ако сте го споделили с някого, той ще стане недостъпен. Сигурен ли си, че искаш да продължиш?",
"MoveToTrashFolder": "На път сте да изтриете тази папка? Моля, обърнете внимание, че ако сте го споделили с някого, той ще стане недостъпен. Сигурен ли си, че искаш да продължиш?",
"MoveToTrashFile": "На път сте да изтриете този файл. Моля, обърнете внимание, че ако сте го споделили с някого, той ще стане недостъпен. Файлът ще бъде окончателно изтрит след 30 дни. Сигурен ли си, че искаш да продължиш?",
"MoveToTrashFolder": "На път сте да изтриете тази папка. Моля, обърнете внимание, че ако сте го споделили с някого, той ще стане недостъпен. Сигурен ли си, че искаш да продължиш?",
"MoveToTrashFolderFromPersonal": "На път сте да изтриете тази папка. Сигурни ли сте, че искате да продължите?",
"MoveToTrashItems": "На път сте да изтриете тези елементи. Моля, имайте предвид, че ако сте ги споделили с някого, те ще станат недостъпни. Сигурни ли сте, че искате да продължите?",
"MoveToTrashTitle": "Преместване в кошчето?",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Копирай {{element}}",
"TooltipElementsCopyMessage": "Копирай {{element}} елемента",
"TooltipElementsMoveMessage": "Премести {{element}} елемента",
"TrashEmptyDescription": "Разделът 'Кошче' е мястото, където се преместват всички изтрити файлове. Можете или да ги възстановите, в случай че бъдат изтрити по погрешка или да ги изтриете за постоянно. Моля, обърнете внимание, че когато изтриете файловете от 'Кошчето', те вече не могат да бъдат възстановени.",
"TrashEmptyDescription": "Разделът 'Кошче' е мястото, където се преместват всички изтрити файлове. Можете или да ги възстановите, в случай че бъдат изтрити по погрешка или да ги изтриете за постоянно. Файловете в 'Кошчето' се изтриват автоматично след 30 дни. Моля, обърнете внимание, че когато изтриете файловете от 'Кошчето', те вече не могат да бъдат възстановени.",
"TrashErasureWarning": "Елементите в кошчето се изтриват автоматично след 30 дни.",
"UnarchivedRoomAction": "Стаята '{{name}}' е изкарана от архива.",
"UnarchivedRoomsAction": "Стаите са изкарани от архива.",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Zkopírovat {{element}}",
"TooltipElementsCopyMessage": "Zkopírovat prvky {{element}}",
"TooltipElementsMoveMessage": "Přesunout prvky {{element}}",
"TrashEmptyDescription": "Sekce 'Koš' je místo, kam jsou všechny smazané soubory přemístěny. Můžete je obnovit v případě, že byly smazány nedopatřením nebo je odstraňte trvale. Prosím berte v úvahu, že pokud vymažete Vaše soubory z 'Koše', již je nemůžete znovu obnovit.",
"TrashEmptyDescription": "Sekce 'Koš' je místo, kam jsou všechny smazané soubory přemístěny. Můžete je obnovit v případě, že byly smazány nedopatřením nebo je odstraňte trvale. Soubory v 'Koši' se automaticky smažou po 30 dnech. Prosím berte v úvahu, že pokud vymažete Vaše soubory z 'Koše', již je nemůžete znovu obnovit.",
"TrashErasureWarning": "Položky v koši se automaticky odstraní po 30 dnech.",
"UnarchivedRoomAction": "Místnost '{{name}}' není archivována.",
"UnarchivedRoomsAction": "Místnosti nejsou archivovány.",

View File

@ -5,10 +5,10 @@
"DeleteRoom": "Sie löschen diesen Raum. Dies kann nicht rückgängig gemacht.",
"DeleteRooms": "Sie möchten diese Räume löschen. Dies kann nicht rückgängig gemacht.",
"MoveToTrashButton": "In den Papierkorb verschieben",
"MoveToTrashFile": "Möchten Sie wirklich das Dokument löschen? Bitte beachten Sie, dass es nicht mehr verfügbar wird, wenn Sie es mit jemandem geteilt haben. Möchten Sie fortsetzen?",
"MoveToTrashFolder": "Möchten Sie wirklich den Ordner löschen? Bitte beachten Sie, dass es nicht mehr verfügbar wird, wenn Sie ihn mit jemandem geteilt haben. Möchten Sie fortsetzen?",
"MoveToTrashFile": "Möchten Sie wirklich das Dokument löschen. Bitte beachten Sie, dass es nicht mehr verfügbar wird, wenn Sie es mit jemandem geteilt haben. Die Datei wird in 30 Tagen endgültig gelöscht. Möchten Sie fortsetzen?",
"MoveToTrashFolder": "Möchten Sie wirklich den Ordner löschen. Bitte beachten Sie, dass es nicht mehr verfügbar wird, wenn Sie ihn mit jemandem geteilt haben. Möchten Sie fortsetzen?",
"MoveToTrashFolderFromPersonal": "Sie möchten diesen Ordner löschen. Fortfahren?",
"MoveToTrashItems": "Möchten Sie wirklich diese Elemente löschen? Bitte beachten Sie, dass die Dateien nicht mehr verfügbar werden, wenn Sie diese vorher freigegeben haben. Möchten Sie fortsetzen?",
"MoveToTrashItems": "Möchten Sie wirklich diese Elemente löschen. Bitte beachten Sie, dass die Dateien nicht mehr verfügbar werden, wenn Sie diese vorher freigegeben haben. Möchten Sie fortsetzen?",
"MoveToTrashTitle": "In Papierkorb verschieben?",
"UnsubscribeButton": "Abbestellen",
"UnsubscribeNote": "Sind Sie sicher, dass Sie die ausgewählten Elemente aus der Liste abbestellen möchten?",

View File

@ -143,7 +143,7 @@
"TooltipElementCopyMessage": "Kopieren {{element}}",
"TooltipElementsCopyMessage": "Kopieren {{element}} Element(e)",
"TooltipElementsMoveMessage": "{{element}} Element(e) verschieben",
"TrashEmptyDescription": "Die Sektion 'Papierkorb' enthält alle gelöschten Dateien. Sie können diese Dokumente entweder wiederherstellen, wenn sie versehentlich gelöscht wurden, oder unwiderruflich entfernen. Bitte beachten Sie, wenn Sie die Dateien aus dem 'Papierkorb' entfernen, können diese nicht mehr wiederhergestellt werden.",
"TrashEmptyDescription": "Die Sektion 'Papierkorb' enthält alle gelöschten Dateien. Sie können diese Dokumente entweder wiederherstellen, wenn sie versehentlich gelöscht wurden, oder unwiderruflich entfernen. Dateien im 'Papierkorb' werden nach 30 Tagen automatisch gelöscht. Bitte beachten Sie, wenn Sie die Dateien aus dem 'Papierkorb' entfernen, können diese nicht mehr wiederhergestellt werden.",
"TrashErasureWarning": "Objekte im Papierkorb werden nach 30 Tagen automatisch gelöscht.",
"UnarchivedRoomAction": "Der Raum '{{name}}' ist nicht archiviert.",
"UnarchivedRoomsAction": "Die Räume sind nicht archiviert.",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Αντιγραφή {{element}}",
"TooltipElementsCopyMessage": "Αντιγραφή στοιχείων {{element}}",
"TooltipElementsMoveMessage": "Μετακίνηση στοιχείων {{element}}",
"TrashEmptyDescription": "Όλα τα διαγραμμένα αρχεία μεταφέρονται στον Κάδο ανακύκλωσης. Επαναφέρετε τα αρχεία που διαγράφηκαν κατά λάθος ή διαγράψτε τα οριστικά. Λάβετε υπόψη ότι τα αρχεία που έχουν διαγραφεί από τον Κάδο ανακύκλωσης δεν μπορούν πλέον να ανακτηθούν",
"TrashEmptyDescription": "Όλα τα διαγραμμένα αρχεία μεταφέρονται στον Κάδο ανακύκλωσης. Επαναφέρετε τα αρχεία που διαγράφηκαν κατά λάθος ή διαγράψτε τα οριστικά. Τα αρχεία στον Κάδος απορριμμάτων διαγράφονται αυτόματα μετά από 30 ημέρες. Λάβετε υπόψη ότι τα αρχεία που έχουν διαγραφεί από τον Κάδο ανακύκλωσης δεν μπορούν πλέον να ανακτηθούν.",
"TrashErasureWarning": "Τα αντικείμενα στον Κάδο Απορριμμάτων διαγράφονται αυτόματα μετά από 30 ημέρες.",
"UnarchivedRoomAction": "Το δωμάτιο '{{name}}' δεν έχει αρχειοθετηθεί.",
"UnarchivedRoomsAction": "Τα δωμάτια δεν έχουν αρχειοθετηθεί.",

View File

@ -118,6 +118,7 @@
"EnterTitle": "Enter title",
"ErrorMessageBruteForceProtection": "Specified argument was out of the range of valid values.",
"ForcePathStyle": "Force Path Style",
"IncludedInBusiness": "Included in Business plan",
"IntegrationRequest": "Missing a useful integration or component in ONLYOFFICE DocSpace? Leave a request to our team and we will look into that.",
"IPSecurity": "IP Security",
"IPSecurityDescription": "<1>IP Security</1> is used to restrict login to the space from all IP addresses except certain addresses. You can set the allowed IP addresses using either exact IP addresses in the IPv4 format (#.#.#.#, where # is a numeric value from 0 to 255), IP range (in the #.#.#.#-#.#.#.# format), or CIDR masking (in the #.#.#.#/# format). The IP security does not work for space owners, they can access the space from any IP address. Rules set in the For all users section apply to full access administrators as well. At the same time, you can set additional rules for full access administrators in the corresponding section.",

View File

@ -143,7 +143,7 @@
"TooltipElementCopyMessage": "Copiar {{element}}",
"TooltipElementsCopyMessage": "Copiar {{element}} elementos",
"TooltipElementsMoveMessage": "Mover {{element}} elementos",
"TrashEmptyDescription": "La sección 'Papelera de reciclaje' es a donde se mueven todos los archivos borrados. Usted puede restaurarlos en el caso si ellos fueron eliminados por error o eliminarlos de forma permanente. Tenga en cuenta, que cuando usted elimina los archivos de la 'Papelera de reciclaje' ellos no pueden ser recuperados.",
"TrashEmptyDescription": "La sección 'Papelera de reciclaje' es a donde se mueven todos los archivos borrados. Usted puede restaurarlos en el caso si ellos fueron eliminados por error o eliminarlos de forma permanente. Los archivos en la 'Papelera de reciclaje' se eliminan automáticamente después de 30 días. Tenga en cuenta, que cuando usted elimina los archivos de la 'Papelera de reciclaje' ellos no pueden ser recuperados.",
"TrashErasureWarning": "Los elementos de la papelera se eliminan automáticamente después de 30 días.",
"UnarchivedRoomAction": "La sala '{{name}}' está desarchivada.",
"UnarchivedRoomsAction": "Las salas están desarchivadas.",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Kopioi {{element}}",
"TooltipElementsCopyMessage": "Kopioi {{element}} elementit",
"TooltipElementsMoveMessage": "Siirrä {{element}} elementit",
"TrashEmptyDescription": "Kaikki poistetut tiedostot siirretään 'Roskakoriin'. Voit palauttaa vahingossa poistetut tiedostot tai poistaa ne pysyvästi. Huomaa, että 'Roskakorista' poistettuja tiedostoja ei voida palauttaa.",
"TrashEmptyDescription": "Kaikki poistetut tiedostot siirretään 'Roskakoriin'. Voit palauttaa vahingossa poistetut tiedostot tai poistaa ne pysyvästi. Roskakorin tiedostot poistetaan automaattisesti 30 päivän kuluttua. Huomaa, että 'Roskakorista' poistettuja tiedostoja ei voida palauttaa.",
"TrashErasureWarning": "Roskakorin kohteet poistetaan automaattisesti 30 päivän jälkeen.",
"UnarchivedRoomAction": "Huone '{{name}}' on arkistoimaton.",
"UnarchivedRoomsAction": "Huoneet ovat arkistoimattomia.",

View File

@ -5,10 +5,10 @@
"DeleteRoom": "Vous êtes sur le point de supprimer cette salle. Vous ne pourrez pas la restaurer.",
"DeleteRooms": "Vous êtes sur le point de supprimer ces salles. Vous ne pourrez pas les restaurer.",
"MoveToTrashButton": "Mettre dans la corbeille",
"MoveToTrashFile": "Vous êtes sur le point de supprimer ce fichier? Veuillez noter que si vous l'avez partagé avec quelqu'un, il deviendra indisponible. Êtes-vous sûr de vouloir continuer?",
"MoveToTrashFolder": "Vous êtes sur le point de supprimer ce dossier? Veuillez noter que si vous l'avez partagé avec quelqu'un, il deviendra indisponible. Êtes-vous sûr de vouloir continuer?",
"MoveToTrashFile": "Vous êtes sur le point de supprimer ce fichier. Veuillez noter que si vous l'avez partagé avec quelqu'un, il deviendra indisponible. Le fichier sera définitivement supprimé dans 30 jours. Êtes-vous sûr de vouloir continuer?",
"MoveToTrashFolder": "Vous êtes sur le point de supprimer ce dossier. Veuillez noter que si vous l'avez partagé avec quelqu'un, il deviendra indisponible. Êtes-vous sûr de vouloir continuer?",
"MoveToTrashFolderFromPersonal": "Vous êtes sur le point de supprimer ce dossier. Êtes-vous sûr de vouloir continuer ?",
"MoveToTrashItems": "Vous êtes sur le point de supprimer ces éléments? Veuillez noter que si vous les avez partagés avec quelqu'un, ils deviendront indisponibles. Êtes-vous sûr de vouloir continuer?",
"MoveToTrashItems": "Vous êtes sur le point de supprimer ces éléments. Veuillez noter que si vous les avez partagés avec quelqu'un, ils deviendront indisponibles. Êtes-vous sûr de vouloir continuer?",
"MoveToTrashTitle": "Déplacer vers la corbeille ?",
"UnsubscribeButton": "Se désabonner",
"UnsubscribeNote": "Êtes-vous sûr de vouloir vous désabonner des éléments sélectionnés dans la liste ?",

View File

@ -143,7 +143,7 @@
"TooltipElementCopyMessage": "Copier {{element}}",
"TooltipElementsCopyMessage": "Copier {{element}} des éléments",
"TooltipElementsMoveMessage": "Déplacer les éléments {{element}}",
"TrashEmptyDescription": "La section 'Corbeille' contient les fichiers supprimés. Vous pouvez les restaurer s'ils ont été supprimés par erreur ou les éliminer de manière permanente. Il est à noter que quand vous supprimez les fichiers de la 'Corbeille' ils ne peuvent pas être restaurés.",
"TrashEmptyDescription": "La section 'Corbeille' contient les fichiers supprimés. Vous pouvez les restaurer s'ils ont été supprimés par erreur ou les éliminer de manière permanente. Les fichiers dans la 'Corbeille' sont automatiquement supprimés après 30 jours. Il est à noter que quand vous supprimez les fichiers de la 'Corbeille' ils ne peuvent pas être restaurés.",
"TrashErasureWarning": "Les éléments placés dans la corbeille sont automatiquement supprimés dans les 30 jours.",
"UnarchivedRoomAction": "La salle '{{name}}' n'est plus archivée.",
"UnarchivedRoomsAction": "Les salles ne sont plus archivées.",

View File

@ -143,7 +143,7 @@
"TooltipElementCopyMessage": "Պատճենել {{element}}",
"TooltipElementsCopyMessage": "Պատճենել {{element}} տարրեր",
"TooltipElementsMoveMessage": "Տեղափոխել {{element}} տարրեր",
"TrashEmptyDescription": "Բոլոր ջնջված ֆայլերը տեղափոխվում են 'Աղբարկղ'. Վերականգնել սխալմամբ ջնջված ֆայլերը կամ մշտապես ջնջել դրանք. Խնդրում ենք նկատի ունենալ, որ 'Աղբարկղ'-ից ջնջված ֆայլերն այլևս չեն կարող վերականգնվել։",
"TrashEmptyDescription": "Բոլոր ջնջված ֆայլերը տեղափոխվում են 'Աղբարկղ'. Վերականգնել սխալմամբ ջնջված ֆայլերը կամ մշտապես ջնջել դրանք. 'Աղբարկղ'-ի ֆայլերը ավտոմատ կերպով ջնջվում են 30 օր հետո: Խնդրում ենք նկատի ունենալ, որ 'Աղբարկղ'-ից ջնջված ֆայլերն այլևս չեն կարող վերականգնվել։",
"TrashErasureWarning": "Աղբարկղում գտնվող տարրերն ավտոմատ կերպով ջնջվում են 30 օր հետո:",
"UnarchivedRoomAction": "'{{name}}' սենյակը հանված է արխիվից:",
"UnarchivedRoomsAction": "Սենյակները արխիվացված են։",

View File

@ -5,10 +5,10 @@
"DeleteRoom": "Stai per eliminare questa stanza. Non sarai in grado di ripristinarla.",
"DeleteRooms": "Stai per eliminare queste stanze. Non sarai in grado di ripristinarli.",
"MoveToTrashButton": "Spostare nel Cestino",
"MoveToTrashFile": "Stai per eliminare questo file? Tieni presente che se lo hai condiviso con qualcuno, non sarà più disponibile. Sei sicuro di voler continuare?",
"MoveToTrashFolder": "Stai per eliminare questa cartella? Tieni presente che, se l'hai condivisa con qualcuno, non sarà più disponibile. Sei sicuro di voler continuare?",
"MoveToTrashFile": "Stai per eliminare questo file. Tieni presente che se lo hai condiviso con qualcuno, non sarà più disponibile. Il file verrà eliminato definitivamente entro 30 giorni. Sei sicuro di voler continuare?",
"MoveToTrashFolder": "Stai per eliminare questa cartella. Tieni presente che, se l'hai condivisa con qualcuno, non sarà più disponibile. Sei sicuro di voler continuare?",
"MoveToTrashFolderFromPersonal": "Stai per eliminare questa cartella. Sei sicuro di voler continuare?",
"MoveToTrashItems": "Stai per eliminare questi elementi? Tieni presente che se li hai condivisi con qualcuno, non saranno più disponibili. Sei sicuro di voler continuare?",
"MoveToTrashItems": "Stai per eliminare questi elementi. Tieni presente che se li hai condivisi con qualcuno, non saranno più disponibili. Sei sicuro di voler continuare?",
"MoveToTrashTitle": "Spostare nel Cestino?",
"UnsubscribeButton": "Annullare l'iscrizione",
"UnsubscribeNote": "Sei sicuro di voler cancellarti dagli elementi selezionati nell'elenco?",

View File

@ -143,7 +143,7 @@
"TooltipElementCopyMessage": "Copia {{element}}",
"TooltipElementsCopyMessage": "Copia {{element}} elementi",
"TooltipElementsMoveMessage": "Sposta {{element}} elementi",
"TrashEmptyDescription": "Tutti i file eliminati vengono spostati nel 'Cestino'. Ripristina i file cancellati per errore o cancellali definitivamente. Tieni presente che i file eliminati dal 'Cestino' non possono più essere ripristinati.",
"TrashEmptyDescription": "Tutti i file eliminati vengono spostati nel 'Cestino'. Ripristina i file cancellati per errore o cancellali definitivamente. I file nel \"Cestino\" verranno automaticamente eliminati dopo 30 giorni. Tieni presente che i file eliminati dal 'Cestino' non possono più essere ripristinati.",
"TrashErasureWarning": "Gli elementi nel Cestino vengono automaticamente eliminati dopo 30 giorni.",
"UnarchivedRoomAction": "La stanza '{{name}}' è stata rimossa dall'archivio.",
"UnarchivedRoomsAction": "Le stanze non sono state archiviate.",

View File

@ -5,7 +5,7 @@
"DeleteRoom": "このルームを削除しようとしています。復元することはできません。",
"DeleteRooms": "このルームを削除しようとしています。復元することはできません。",
"MoveToTrashButton": "ゴミ箱への移動",
"MoveToTrashFile": "このファイルを削除しようとしています。そうすると、共有されたユーザーに利用可能できなくなります。ファイルを削除したいを確認してください。",
"MoveToTrashFile": "このファイルを削除しようとしています。そうすると、共有されたユーザーに利用可能できなくなります。ファイルは30日後に完全に削除されます。ファイルを削除したいを確認してください。",
"MoveToTrashFolder": "このフォルダーを削除しようとしています。そうすると、共有されたユーザーに利用可能できなくなります。フォルダーを削除したいを確認してください。",
"MoveToTrashFolderFromPersonal": "このフォルダを削除しようとしています。このまま続けますか?",
"MoveToTrashItems": "この要素を削除しようとしています。そうすると、共有されたユーザーに利用可能できなくなります。要素の削除を確認してください。",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "{{element}}をコピー",
"TooltipElementsCopyMessage": " {{element}} 要素をコピー",
"TooltipElementsMoveMessage": " {{element}} 要素を移動",
"TrashEmptyDescription": "すべての削除されたファイルは「ごみ箱」に移動されます。間違って削除されたファイルをを復元するか、完全に削除することができます。「ごみ箱」から削除されたファイルは、もう復元できないことにご注意ください。",
"TrashEmptyDescription": "すべての削除されたファイルは「ごみ箱」に移動されます。間違って削除されたファイルをを復元するか、完全に削除することができます。「ゴミ箱」にあるファイルは30日後に自動的に削除されます。「ごみ箱」から削除されたファイルは、もう復元できないことにご注意ください。",
"TrashErasureWarning": "ゴミ箱にあるアイテムは、30日後に自動的に削除されます。",
"UnarchivedRoomAction": "ルーム '{{name}}' はアーカイブが解除されました。",
"UnarchivedRoomsAction": "ルームはアーカイブが解除されました。",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "{{element}} 복사",
"TooltipElementsCopyMessage": "{{element}} 요소 복사",
"TooltipElementsMoveMessage": "{{element}} 요소 이동",
"TrashEmptyDescription": "모든 삭제 된 파일이 이동되는 위치는 '휴지통'섹션입니다. 실수로 삭제된 경우, 복원하거나 완전삭제를 할수있습니다. 참고하시기 바랍니다, '휴지통'에서 파일을 삭제하변 더 이상 복원 할수없습니다.",
"TrashEmptyDescription": "모든 삭제 된 파일이 이동되는 위치는 '휴지통'섹션입니다. 실수로 삭제된 경우, 복원하거나 완전삭제를 할수있습니다. '휴지통'에 있는 파일은 30일 후에 자동으로 삭제됩니다. 참고하시기 바랍니다, '휴지통'에서 파일을 삭제하변 더 이상 복원 할수없습니다.",
"TrashErasureWarning": "휴지통에 든 항목은 30일 후에 자동으로 삭제됩니다.",
"UnarchivedRoomAction": "'{{name}}' 방의 아카이브가 취소되었습니다.",
"UnarchivedRoomsAction": "방의 아카이브가 취소되었습니다.",

View File

@ -5,8 +5,8 @@
"DeleteRoom": "Jūs gatavojaties izdzēst šo telpu. Jūs nevarēsiet to atjaunot.",
"DeleteRooms": "Jūs gatavojaties izdzēst šīs telpas. Jūs nevarēsiet tos atjaunot.",
"MoveToTrashButton": "Pārvietot uz miskasti",
"MoveToTrashFile": "Vai grasāties dzēst šo failu? Lūdzu, ņemiet vērā, ka, ja esat to kopīgojuši ar kādu, tas vairs nebūs pieejams. Vai vēlaties turpināt?",
"MoveToTrashFolder": "Vai grasāties dzēst šo mapi? Lūdzu, ņemiet vērā, ka ja esat to ar kādu kopīgojuši, tā vairs nebūs pieejama. Vai vēlaties turpināt?",
"MoveToTrashFile": "Vai grasāties dzēst šo failu. Lūdzu, ņemiet vērā, ka, ja esat to kopīgojuši ar kādu, tas vairs nebūs pieejams. Fails tiks neatgriezeniski dzēsts pēc 30 dienām. Vai vēlaties turpināt?",
"MoveToTrashFolder": "Vai grasāties dzēst šo mapi. Lūdzu, ņemiet vērā, ka ja esat to ar kādu kopīgojuši, tā vairs nebūs pieejama. Vai vēlaties turpināt?",
"MoveToTrashFolderFromPersonal": "Jūs gatavojaties izdzēst šo mapi. Vai tiešām vēlaties turpināt?",
"MoveToTrashItems": "Jūs gatavojaties izdzēst šos vienumus. Lūdzu, ņemiet vērā, ka gadījumā, ja tos kopīgosiet ar kādu citu personu, tie kļūs nepieejami",
"MoveToTrashTitle": "Izdzēst?",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Kopēt {{element}}",
"TooltipElementsCopyMessage": "Kopēt {{element}} elementus",
"TooltipElementsMoveMessage": "Pārvietot {{element}} elementus",
"TrashEmptyDescription": "'Atkritne' ir sadaļā kur ir pārvietoti visi izdzēstie faili. Jūs varat vai nu atjaunot tos, ja tie tiek izdzēsti kļūdas dēļ vai izdzēst pavisam. Lūdzu, ņemiet vērā, ka, ja izdzēšat failus no 'Atkritne' tās vairs nevar būt atjaunoti.",
"TrashEmptyDescription": "'Atkritne' ir sadaļā kur ir pārvietoti visi izdzēstie faili. Jūs varat vai nu atjaunot tos, ja tie tiek izdzēsti kļūdas dēļ vai izdzēst pavisam. Faili miskastē tiek automātiski izdzēsti pēc 30 dienām. Lūdzu, ņemiet vērā, ka, ja izdzēšat failus no 'Atkritne' tās vairs nevar būt atjaunoti.",
"TrashErasureWarning": "Atkritnē esošie vienumi tiek automātiski izdzēsti pēc 30 dienām.",
"UnarchivedRoomAction": "Telpa '{{name}}' nav arhivēta.",
"UnarchivedRoomsAction": "Telpas nav arhivētas.",

View File

@ -5,7 +5,7 @@
"DeleteRoom": "U staat op het punt deze kamer te verwijderen. U kunt dit niet meer herstellen.",
"DeleteRooms": "U staat op het punt deze kamers te verwijderen. U kunt ze niet meer herstellen.",
"MoveToTrashButton": "Verplaats naar Prullenbak",
"MoveToTrashFile": "U staat op het punt dit bestand te verwijderen. Denk eraan dat, indien u dit deelde met iemand anders, het onbeschikbaar zal worden. Bent u zeker dat u wil doorgaan?",
"MoveToTrashFile": "U staat op het punt dit bestand te verwijderen. Denk eraan dat, indien u dit deelde met iemand anders, het onbeschikbaar zal worden. Het bestand wordt binnen 30 dagen definitief verwijderd. Bent u zeker dat u wil doorgaan?",
"MoveToTrashFolder": "U staat op het punt deze map te verwijderen. Denk eraan dat, indien u deze deelde met iemand anders, deze onbeschikbaar zal worden. Bent u zeker dat u wil doorgaan?",
"MoveToTrashFolderFromPersonal": "U staat op het punt deze map te verwijderen. Weet u zeker dat u door wilt gaan?",
"MoveToTrashItems": "U staat op het punt deze items te verwijderen. Als u ze met iemand heeft gedeeld, zijn ze niet meer beschikbaar. Weet u zeker dat u door wilt gaan?",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Kopieer {{element}}",
"TooltipElementsCopyMessage": "Kopieer {{element}} elementen",
"TooltipElementsMoveMessage": "Kopieer {{element}} elementen",
"TrashEmptyDescription": "Alle verwijderde bestanden worden verplaatst naar de 'Prullenbak'. Je kan deze terugzetten als ze per ongeluk verwijderd zijn of je kan ze permanent verwijderen. Wees ervan bewust dat als de bestanden eenmaal uit de Prullenbak zijn verwijderd deze niet meer terug te krijgen zijn.",
"TrashEmptyDescription": "Alle verwijderde bestanden worden verplaatst naar de 'Prullenbak'. Je kan deze terugzetten als ze per ongeluk verwijderd zijn of je kan ze permanent verwijderen. Bestanden in de 'Prullenbak' worden na 30 dagen automatisch verwijderd. Wees ervan bewust dat als de bestanden eenmaal uit de Prullenbak zijn verwijderd deze niet meer terug te krijgen zijn.",
"TrashErasureWarning": "Items in de Prullenbak worden na 30 dagen automatisch verwijderd.",
"UnarchivedRoomAction": "De kamer '{{name}}' is niet meer gearchiveerd.",
"UnarchivedRoomsAction": "De kamers zijn niet meer gearchiveerd.",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Skopiuj {{element}}",
"TooltipElementsCopyMessage": "Skopiuj elementy {{element}}",
"TooltipElementsMoveMessage": "Przenieś elementy {{element}}",
"TrashEmptyDescription": "Dział 'Kosz' zawiera wszystkie usunięte pliki. Możesz przywrócić pliki jeśli zostały one usunięte przez pomyłkę lub usunąć ostatecznie. Po usunięciu ostatecznym przywrócenie już nie będzie możliwe.",
"TrashEmptyDescription": "Dział 'Kosz' zawiera wszystkie usunięte pliki. Możesz przywrócić pliki jeśli zostały one usunięte przez pomyłkę lub usunąć ostatecznie. Pliki w 'Koszu' są automatycznie usuwane po 30 dniach. Po usunięciu ostatecznym przywrócenie już nie będzie możliwe.",
"TrashErasureWarning": "Pliki w Koszu zostaną usunięte automatycznie po 30 dniach.",
"UnarchivedRoomAction": "Pokój '{{name}}' został przywrócony z archiwum.",
"UnarchivedRoomsAction": "Pokoje zostały przywrócone z archiwum.",

View File

@ -5,8 +5,8 @@
"DeleteRoom": "Você está prestes a excluir esta sala. Você não será capaz de restaurá-lo.",
"DeleteRooms": "Você está prestes a excluir estas salas. Você não poderá restaurá-los.",
"MoveToTrashButton": "Mover para a lixeira",
"MoveToTrashFile": "Você está prestes a apagar este arquivo? Observe que, se você o compartilhou com alguém, ele se tornará indisponível. Você tem certeza de que quer continuar?",
"MoveToTrashFolder": "Você está prestes a apagar esta pasta? Observe que, se você a tiver compartilhado com alguém, ela ficará indisponível. Você tem certeza de que quer continuar?",
"MoveToTrashFile": "Você está prestes a apagar este arquivo. Observe que, se você o compartilhou com alguém, ele se tornará indisponível. O arquivo será excluído permanentemente em 30 dias. Você tem certeza de que quer continuar?",
"MoveToTrashFolder": "Você está prestes a apagar esta pasta. Observe que, se você a tiver compartilhado com alguém, ela ficará indisponível. Você tem certeza de que quer continuar?",
"MoveToTrashFolderFromPersonal": "Você está prestes a excluir esta pasta. Você tem certeza que quer continuar?",
"MoveToTrashItems": "Você está prestes a excluir esses itens. Observe que, se você os tiver compartilhado com alguém, eles ficarão indisponíveis. Você tem certeza que quer continuar?",
"MoveToTrashTitle": "Mover para a lixeira?",

View File

@ -143,7 +143,7 @@
"TooltipElementCopyMessage": "Cópia {{element}}",
"TooltipElementsCopyMessage": "Cópia {{element}} elementos",
"TooltipElementsMoveMessage": "Mover {{element}} elementos",
"TrashEmptyDescription": "A sessão 'Lixeira' é o lugar para o qual todos os arquivos excluídos serão movidos. Você pode restaurá-los caso tenha excluído por engano ou permanentemente. Observe que quando você exclui arquivos da \"Lixeira\", eles não poderão mais ser restaurados.",
"TrashEmptyDescription": "A sessão 'Lixeira' é o lugar para o qual todos os arquivos excluídos serão movidos. Você pode restaurá-los caso tenha excluído por engano ou permanentemente. Os arquivos na 'Lixeira' são excluídos automaticamente após 30 dias. Observe que quando você exclui arquivos da \"Lixeira\", eles não poderão mais ser restaurados.",
"TrashErasureWarning": "Os itens na Lixeira são excluídos automaticamente após 30 dias.",
"UnarchivedRoomAction": "A sala '{{name}}' foi desarquivada.",
"UnarchivedRoomsAction": "As salas são desarquivadas.",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Copiar {{element}}",
"TooltipElementsCopyMessage": "Copiar {{element}} elementos",
"TooltipElementsMoveMessage": "Mover {{element}} elementos",
"TrashEmptyDescription": "A secção 'Lixo' é para onde todos os arquivos eliminados são movidos. Pode recuperá-los no caso de terem sido eliminados por engano ou excluí-los permanentemente. Por favor, note que quando eliminar os ficheiros do 'Lixo' não podem ser recuperados no futuro.",
"TrashEmptyDescription": "A secção 'Lixo' é para onde todos os arquivos eliminados são movidos. Pode recuperá-los no caso de terem sido eliminados por engano ou excluí-los permanentemente. Os ficheiros na 'Lixo' são excluídos automaticamente após 30 dias. Por favor, note que quando eliminar os ficheiros do 'Lixo' não podem ser recuperados no futuro.",
"TrashErasureWarning": "Os Itens no Lixo serão automaticamente eliminados após 30 dias.",
"UnarchivedRoomAction": "A sala '{{name}} está desarquivada.",
"UnarchivedRoomsAction": "As salas estão desarquivadas.",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Copiere {{element}}",
"TooltipElementsCopyMessage": "Copiere elemente {{element}}",
"TooltipElementsMoveMessage": "Mutare elemente {{element}}",
"TrashEmptyDescription": "Toate fișierele eliminate sunt mutate în 'Coșul' de gunoi. Puteți să restabiliți fișierele pe care le-ați mutat din greșeală sau să le ștergeți definitiv. Vă rugăm să rețineți că nu puteți recupera fișierele șterse din 'Coșul' de gunoi.",
"TrashEmptyDescription": "Toate fișierele eliminate sunt mutate în 'Coșul' de gunoi. Puteți să restabiliți fișierele pe care le-ați mutat din greșeală sau să le ștergeți definitiv. Fișierele din coșul de gunoi sunt șterse automat după 30 de zile. Vă rugăm să rețineți că nu puteți recupera fișierele șterse din 'Coșul' de gunoi.",
"TrashErasureWarning": "Elementele din Coșul de gunoi sunt șterse automat după 30 zile.",
"UnarchivedRoomAction": "Sala '{{name}}' este dezarhivată.",
"UnarchivedRoomsAction": "Sălile sunt dezarhivate.",

View File

@ -5,10 +5,10 @@
"DeleteRoom": "Вы собираетесь удалить эту комнату? Вы не сможете восстановить ее.",
"DeleteRooms": "Вы собираетесь удалить эти комнаты? Вы не сможете восстановить их.",
"MoveToTrashButton": "Переместить в корзину",
"MoveToTrashFile": "Вы собираетесь удалить этот файл? Пожалуйста, обратите внимание, что если вы предоставили кому-то доступ к нему, он станет недоступен. Вы уверены, что хотите продолжить?",
"MoveToTrashFolder": "Вы собираетесь удалить эту папку? Пожалуйста, обратите внимание, что если вы предоставили кому-то доступ к ней, она станет недоступна. Вы уверены, что хотите продолжить?",
"MoveToTrashFile": "Вы собираетесь удалить этот файл. Пожалуйста, обратите внимание, что если вы предоставили кому-то доступ к нему, он станет недоступен. Файл будет окончательно удален через 30 дней. Вы уверены, что хотите продолжить?",
"MoveToTrashFolder": "Вы собираетесь удалить эту папку. Пожалуйста, обратите внимание, что если вы предоставили кому-то доступ к ней, она станет недоступна. Вы уверены, что хотите продолжить?",
"MoveToTrashFolderFromPersonal": "Вы собираетесь удалить этот папку. Вы уверены, что хотите продолжить?",
"MoveToTrashItems": "Вы собираетесь удалить эти элементы? Пожалуйста, обратите внимание, что если вы предоставили кому-то доступ к ним, они станут недоступны. Вы уверены, что хотите продолжить?",
"MoveToTrashItems": "Вы собираетесь удалить эти элементы. Пожалуйста, обратите внимание, что если вы предоставили кому-то доступ к ним, они станут недоступны. Вы уверены, что хотите продолжить?",
"MoveToTrashTitle": "Переместить в Корзину?",
"UnsubscribeButton": "Отписаться",
"UnsubscribeNote": "Вы действительно хотите отписаться от выделенных элементов из списка?",

View File

@ -143,7 +143,7 @@
"TooltipElementCopyMessage": "Скопировать {{element}}",
"TooltipElementsCopyMessage": "Скопировать {{element}} элемента(ов)",
"TooltipElementsMoveMessage": "Переместить {{element}} элемента(ов)",
"TrashEmptyDescription": "В раздел 'Корзина' перемещаются все удаленные файлы. Восстанавливайте файлы, удаленные по ошибке, или удаляйте их окончательно. Пожалуйста, обратите внимание, что файлы, удаленные из 'Корзины', больше нельзя восстановить.",
"TrashEmptyDescription": "В раздел 'Корзина' перемещаются все удаленные файлы. Восстанавливайте файлы, удаленные по ошибке, или удаляйте их окончательно. Файлы в 'Корзине' автоматически удаляются через 30 дней. Пожалуйста, обратите внимание, что файлы, удаленные из 'Корзины', больше нельзя восстановить.",
"TrashErasureWarning": "Элементы в корзине автоматически удаляются через 30 дней.",
"UnarchivedRoomAction": "Комната '{{name}}' разархивирована",
"UnarchivedRoomsAction": "Комнаты разархивированы",

View File

@ -5,8 +5,8 @@
"DeleteRoom": "Chystáte sa vymazať túto miestnosť. Nemôžete ju obnoviť.",
"DeleteRooms": "Chystáte sa vymazať tieto miestnosti. Nemôžete ich obnoviť.",
"MoveToTrashButton": "Presunúť do koša",
"MoveToTrashFile": "Chystáte sa odstrániť tento súbor? Upozorňujeme, že ak ste ho zdieľali s niekým, stane sa nedostupným. Ste si istý, že chcete pokračovať?",
"MoveToTrashFolder": "Chystáte sa odstrániť tento priečinok? Upozorňujeme, že ak ste ho zdieľali s niekým, stane sa nedostupným. Ste si istý, že chcete pokračovať?",
"MoveToTrashFile": "Chystáte sa odstrániť tento súbor. Upozorňujeme, že ak ste ho zdieľali s niekým, stane sa nedostupným. Súbor bude natrvalo odstránený do 30 dní. Ste si istý, že chcete pokračovať?",
"MoveToTrashFolder": "Chystáte sa odstrániť tento priečinok. Upozorňujeme, že ak ste ho zdieľali s niekým, stane sa nedostupným. Ste si istý, že chcete pokračovať?",
"MoveToTrashFolderFromPersonal": "Chystáte sa vymazať tento priečinok. Ste si istý, že chcete pokračovať?",
"MoveToTrashItems": "Chystáte sa vymazať tieto položky. Upozorňujeme, že ak ich s niekým zdieľate, stanú sa nedostupnými. Ste si istý, že chcete pokračovať?",
"MoveToTrashTitle": "Presunúť do koša?",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Kopírovať {{element}}",
"TooltipElementsCopyMessage": "Kopírovať prvky {{element}}",
"TooltipElementsMoveMessage": "Presunúť prvky {{element}}",
"TrashEmptyDescription": "Do sekcie 'Kôš' sa presúvajú všetky zmazané súbory. V prípade chyby ich môžete obnoviť. Ak zmažete súbory zo sekcie 'Kôš', tak ich nebudete vedieť obnoviť.",
"TrashEmptyDescription": "Do sekcie 'Kôš' sa presúvajú všetky zmazané súbory. V prípade chyby ich môžete obnoviť. Súbory v 'Koši' sa automaticky vymažú po 30 dňoch. Ak zmažete súbory zo sekcie 'Kôš', tak ich nebudete vedieť obnoviť.",
"TrashErasureWarning": "Položky v smetnom koši sa automaticky vymažú po 30 dňoch.",
"UnarchivedRoomAction": "Miestnosť '{{name}}' bola rozbalená z archívu.",
"UnarchivedRoomsAction": "Miestnosti nie sú archivované.",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Kopiraj {{element}}",
"TooltipElementsCopyMessage": "Kopiraj {{element}} elemente",
"TooltipElementsMoveMessage": "Premakni {{element}} elemente",
"TrashEmptyDescription": "Oddelek 'koš' je prostor, kamor so premaknjene vse izbrisane datoteke. Če ste jih izbrisali po pomoti jih lahko obnovite, ali pa jih popolnoma izbrišete. Prosim vedite, da, ko datoteke izbrišete iz 'koša' teh ni več mogoče obnoviti.",
"TrashEmptyDescription": "Oddelek 'Koš' je prostor, kamor so premaknjene vse izbrisane datoteke. Če ste jih izbrisali po pomoti jih lahko obnovite, ali pa jih popolnoma izbrišete. Datoteke v 'Košu' se po 30 dneh samodejno izbrišejo. Prosim vedite, da, ko datoteke izbrišete iz 'koša' teh ni več mogoče obnoviti.",
"TrashErasureWarning": "Elementi v košu se samodejno izbrišejo po 30 dneh.",
"UnarchivedRoomAction": "Soba '{{name}}' ni arhivirana.",
"UnarchivedRoomsAction": "Sobe niso arhivirane.",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Kopyala {{element}}",
"TooltipElementsCopyMessage": "{{element}} öğelerini kopyala",
"TooltipElementsMoveMessage": "{{element}} öğelerini taşı",
"TrashEmptyDescription": "'Çöp Kutusu' bölümü silinen dosyalarınızın taşındığı bölümdür. Yanlışlıkla sildiyseniz geri alabilir yada kalıcı olarak silebilirsiniz. Lütfen unutmayın, 'Çöp kutusundan' dosyaları sildiğiniz zaman artık bir daha geri alamazsınız.",
"TrashEmptyDescription": "'Çöp Kutusu' bölümü silinen dosyalarınızın taşındığı bölümdür. Yanlışlıkla sildiyseniz geri alabilir yada kalıcı olarak silebilirsiniz. 'Çöp Kutusu'ndaki dosyalar 30 gün sonra otomatik olarak silinir. Lütfen unutmayın, 'Çöp kutusundan' dosyaları sildiğiniz zaman artık bir daha geri alamazsınız.",
"TrashErasureWarning": "Çöp Kutusundaki öğeler 30 gün sonra otomatik olarak silinir.",
"UnarchivedRoomAction": "'{{name}}' odası arşivden çıkarıldı.",
"UnarchivedRoomsAction": "Odalar arşivden çıkarıldı.",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Копіювати {{element}}",
"TooltipElementsCopyMessage": "Копіювати елементи {{element}}",
"TooltipElementsMoveMessage": "Перемістити елементи {{element}}",
"TrashEmptyDescription": "У розділі 'Кошик' розміщуються всі видалені файли. Ви можете або відновити їх, якщо вони віддалені помилково, або видалити їх остаточно. Будь ласка, зверніть увагу, що при видаленні файлів з 'Кошика' їх вже не можна буде відновити.",
"TrashEmptyDescription": "У розділі 'Кошик' розміщуються всі видалені файли. Ви можете або відновити їх, якщо вони віддалені помилково, або видалити їх остаточно. Файли в 'Кошику' автоматично видаляються через 30 днів. Будь ласка, зверніть увагу, що при видаленні файлів з 'Кошика' їх вже не можна буде відновити.",
"TrashErasureWarning": "Елементи в Кошику автоматично видаляються через 30 днів.",
"UnarchivedRoomAction": "Кімнату '{{name}}' розархівовано.",
"UnarchivedRoomsAction": "Кімнати розархівовано.",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "Sao chép {{element}}",
"TooltipElementsCopyMessage": "Sao chép {{element}} thành phần",
"TooltipElementsMoveMessage": "Di chuyển {{element}} thành phần",
"TrashEmptyDescription": "Phần 'Thùng rác' là nơi chứa tất cả các file đã xoá. Bạn có thể khôi phục chúng nếu là do xóa nhầm hoặc xóa bỏ chúng vĩnh viễn. Lưu ý rằng khi bạn xóa các file từ 'Thùng rác' chúng sẽ không thể được khôi phục lại.",
"TrashEmptyDescription": "Phần 'Thùng rác' là nơi chứa tất cả các file đã xoá. Bạn có thể khôi phục chúng nếu là do xóa nhầm hoặc xóa bỏ chúng vĩnh viễn. Các tệp trong 'Thùng rác' sẽ tự động bị xóa sau 30 ngày. Lưu ý rằng khi bạn xóa các file từ 'Thùng rác' chúng sẽ không thể được khôi phục lại.",
"TrashErasureWarning": "Các mục trong Thùng rác sẽ tự động bị xóa sau 30 ngày.",
"UnarchivedRoomAction": "Phòng '{{name}}' chưa được sao lưu.",
"UnarchivedRoomsAction": "Các phòng chưa được sao lưu.",

View File

@ -5,10 +5,10 @@
"DeleteRoom": "您即将删除此房间。您将无法使其恢复。",
"DeleteRooms": "您即将删除这些房间。您将无法使其恢复。",
"MoveToTrashButton": "移至垃圾箱",
"MoveToTrashFile": "您要删除该文件请注意,如果您与别人分享了它,该文件将变得不可用。您确定要继续吗?",
"MoveToTrashFolder": "您要删除该文件夹请注意,如果您与别人分享了它,该文件夹将变得不可用。您确定要继续吗?",
"MoveToTrashFile": "您要删除该文件请注意,如果您与别人分享了它,该文件将变得不可用。文件将在 30 天后被永久删除。您确定要继续吗?",
"MoveToTrashFolder": "您要删除该文件夹请注意,如果您与别人分享了它,该文件夹将变得不可用。您确定要继续吗?",
"MoveToTrashFolderFromPersonal": "您即将删除此文件夹。确定要继续吗?",
"MoveToTrashItems": "您要删除该项目请注意,如果您与别人分享了它,该项目将变得不可用。您确定要继续吗?",
"MoveToTrashItems": "您要删除该项目请注意,如果您与别人分享了它,该项目将变得不可用。您确定要继续吗?",
"MoveToTrashTitle": "要移动到垃圾桶吗?",
"UnsubscribeButton": "取消订阅",
"UnsubscribeNote": "您确定要取消订阅列表中的选定项目吗?",

View File

@ -103,7 +103,7 @@
"TooltipElementCopyMessage": "复制{{element}}",
"TooltipElementsCopyMessage": "复制{{element}}元素",
"TooltipElementsMoveMessage": "移动{{element}}元素",
"TrashEmptyDescription": "回收站\"存放的是被删除的文档。您可以选择“还原”或“永久删除”回收站中的文件。请注意:被永久删除的文档将无法再恢复。",
"TrashEmptyDescription": "回收站\"存放的是被删除的文档。您可以选择“还原”或“永久删除”回收站中的文件。\"垃圾桶\"中的文件将在 30 天后自动删除。请注意:被永久删除的文档将无法再恢复。",
"TrashErasureWarning": "垃圾箱中的文件在30天后会自动删除。",
"UnarchivedRoomAction": "房间 '{{name}}' 已取消归档。",
"UnarchivedRoomsAction": "房间已取消归档。",

View File

@ -220,6 +220,8 @@ const CreateUserForm = (props) => {
const signupAccount = {
EmployeeType: linkData.emplType || null,
Email: linkData.email,
Key: linkData.key,
SerializedProfile: profile,
};
@ -341,7 +343,7 @@ const CreateUserForm = (props) => {
<div className="buttonWrapper" key={`${item.provider}ProviderItem`}>
<SocialButton
iconName={icon}
label={getProviderTranslation(label, t)}
label={getProviderTranslation(label, t, false, true)}
className={`socialButton ${className ? className : ""}`}
$iconOptions={iconOptions}
data-url={item.url}
@ -361,7 +363,7 @@ const CreateUserForm = (props) => {
<SocialButton
iconName={SsoReactSvgUrl}
className="socialButton"
label={capabilities?.ssoLabel || getProviderTranslation("sso", t)}
label={capabilities?.ssoLabel || getProviderTranslation("sso", t, false, true)}
onClick={() => (window.location.href = capabilities?.ssoUrl)}
/>
</div>
@ -682,6 +684,7 @@ const CreateUserForm = (props) => {
onSocialLoginClick={onSocialButtonClick}
ssoLabel={capabilities?.ssoLabel}
ssoUrl={capabilities?.ssoUrl}
isSignUp
/>
</RegisterContainer>
</FormWrapper>

View File

@ -123,6 +123,7 @@ const PortalRenaming = (props) => {
setPortalName(portalName);
setPortalNameDefault(portalName);
sessionStorage.clear();
navigate(res);
})

View File

@ -417,7 +417,7 @@ const PortalIntegration = (props) => {
<CategorySubHeader className="copy-window-code">
{t("CopyWindowCode")}
</CategorySubHeader>
<Textarea value={codeBlock} />
<Textarea value={codeBlock} heightTextArea={153} />
</>
);

View File

@ -40,6 +40,7 @@ const RootContainer = styled(Box)`
display: grid;
grid-template-columns: repeat(auto-fill, minmax(293px, 1fr));
gap: 20px;
margin-bottom: 20px;
}
.consumer-item-wrapper {
@ -64,8 +65,11 @@ const RootContainer = styled(Box)`
}
}
.paid-badge {
margin-bottom: 8px;
.business-plan {
display: flex;
gap: 8px;
align-items: center;
margin-bottom: 16px;
}
`;
@ -169,6 +173,13 @@ class ThirdPartyServices extends React.Component {
consumer.name !== "twilio"
);
const freeConsumers = filteredConsumers.filter(
(consumer) => consumer.canSet === false
);
const paidConsumers = filteredConsumers.filter(
(consumer) => !freeConsumers.includes(consumer)
);
const imgSrc = theme.isBase ? IntegrationSvgUrl : IntegrationDarkSvgUrl;
const submitRequest = () =>
@ -177,14 +188,6 @@ class ThirdPartyServices extends React.Component {
return (
<>
<RootContainer className="RootContainer">
{!isThirdPartyAvailable && (
<Badge
backgroundColor="#EDC409"
label={t("Common:Paid")}
className="paid-badge"
isPaidBadge={true}
/>
)}
<Text className="third-party-description">
{t("ThirdPartyTitleDescription")}
</Text>
@ -216,7 +219,37 @@ class ThirdPartyServices extends React.Component {
/>
</Box>
<div className="consumers-list-container">
{filteredConsumers.map((consumer) => (
{freeConsumers.map((consumer) => (
<Box className="consumer-item-wrapper" key={consumer.name}>
<ConsumerItem
consumer={consumer}
dialogVisible={dialogVisible}
isLoading={isLoading}
onChangeLoading={onChangeLoading}
onModalClose={onModalClose}
onModalOpen={onModalOpen}
setConsumer={setConsumer}
updateConsumerProps={updateConsumerProps}
t={t}
isThirdPartyAvailable={isThirdPartyAvailable}
/>
</Box>
))}
</div>
{!isThirdPartyAvailable && (
<div className="business-plan">
<Text fontSize="16px" fontWeight={700}>
{t("IncludedInBusiness")}
</Text>
<Badge
backgroundColor="#EDC409"
label={t("Common:Paid")}
isPaidBadge={true}
/>
</div>
)}
<div className="consumers-list-container">
{paidConsumers.map((consumer) => (
<Box className="consumer-item-wrapper" key={consumer.name}>
<ConsumerItem
consumer={consumer}

Some files were not shown because too many files have changed in this diff Show More