Merge branch 'develop' into bugfix/storybook-fixes
This commit is contained in:
commit
0f23ead295
40
.github/workflows/build-ffvideo.yml
vendored
Normal file
40
.github/workflows/build-ffvideo.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
name: ffvideo build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- release/v1.0.0
|
||||
paths:
|
||||
- 'build/install/docker/**.ffvideo'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [linux/amd64]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
file: ./build/install/docker/Dockerfile.ffvideo
|
||||
push: true
|
||||
tags: onlyoffice/ffvideo:6.0
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -50,3 +50,4 @@ TestsResults/
|
||||
|
||||
**/.yarn/cache
|
||||
**/.yarn/install-state.gz
|
||||
licenses.csv
|
||||
|
46
.yarn/plugins/@yarnpkg/plugin-licenses-audit.cjs
vendored
Normal file
46
.yarn/plugins/@yarnpkg/plugin-licenses-audit.cjs
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -7,5 +7,7 @@ plugins:
|
||||
spec: "@yarnpkg/plugin-interactive-tools"
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
|
||||
spec: "@yarnpkg/plugin-version"
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-licenses-audit.cjs
|
||||
spec: "https://raw.githubusercontent.com/tophat/yarn-plugin-licenses/master/bundles/@yarnpkg/plugin-licenses-audit.js"
|
||||
|
||||
yarnPath: .yarn/releases/yarn-3.2.4.cjs
|
||||
|
@ -41,26 +41,6 @@ elif [ "$UPDATE" = "true" ] && [ "$DOCUMENT_SERVER_INSTALLED" = "true" ]; then
|
||||
apt-get install -y --only-upgrade ${package_sysname}-documentserver
|
||||
fi
|
||||
|
||||
NGINX_ROOT_DIR="/etc/nginx"
|
||||
|
||||
NGINX_WORKER_PROCESSES=${NGINX_WORKER_PROCESSES:-$(grep processor /proc/cpuinfo | wc -l)};
|
||||
NGINX_WORKER_CONNECTIONS=${NGINX_WORKER_CONNECTIONS:-$(ulimit -n)};
|
||||
|
||||
sed 's/^worker_processes.*/'"worker_processes ${NGINX_WORKER_PROCESSES};"'/' -i ${NGINX_ROOT_DIR}/nginx.conf
|
||||
sed 's/worker_connections.*/'"worker_connections ${NGINX_WORKER_CONNECTIONS};"'/' -i ${NGINX_ROOT_DIR}/nginx.conf
|
||||
|
||||
if ! id "nginx" &>/dev/null; then
|
||||
systemctl stop nginx
|
||||
|
||||
rm -dfr /var/log/nginx/*
|
||||
rm -dfr /var/cache/nginx/*
|
||||
useradd -s /bin/false nginx
|
||||
|
||||
systemctl start nginx
|
||||
else
|
||||
systemctl reload nginx
|
||||
fi
|
||||
|
||||
if [ "$PRODUCT_INSTALLED" = "false" ]; then
|
||||
echo ${product} ${product}/db-pwd select $MYSQL_SERVER_PASS | sudo debconf-set-selections
|
||||
echo ${product} ${product}/db-user select $MYSQL_SERVER_USER | sudo debconf-set-selections
|
||||
|
@ -118,14 +118,8 @@ apt-get install -o DPkg::options::="--force-confnew" -yq \
|
||||
postgresql \
|
||||
redis-server \
|
||||
rabbitmq-server \
|
||||
nginx-extras
|
||||
|
||||
if [ -e /etc/redis/redis.conf ]; then
|
||||
sed -i "s/bind .*/bind 127.0.0.1/g" /etc/redis/redis.conf
|
||||
sed -r "/^save\s[0-9]+/d" -i /etc/redis/redis.conf
|
||||
|
||||
service redis-server restart
|
||||
fi
|
||||
nginx-extras \
|
||||
ffmpeg
|
||||
|
||||
if [ ! -e /usr/bin/json ]; then
|
||||
npm i json -g >/dev/null 2>&1
|
||||
|
@ -10,13 +10,6 @@ cat<<EOF
|
||||
|
||||
EOF
|
||||
|
||||
if [ -e /etc/redis.conf ]; then
|
||||
sed -i "s/bind .*/bind 127.0.0.1/g" /etc/redis.conf
|
||||
sed -r "/^save\s[0-9]+/d" -i /etc/redis.conf
|
||||
|
||||
systemctl restart redis
|
||||
fi
|
||||
|
||||
sed "/host\s*all\s*all\s*127\.0\.0\.1\/32\s*ident$/s|ident$|trust|" -i /var/lib/pgsql/data/pg_hba.conf
|
||||
sed "/host\s*all\s*all\s*::1\/128\s*ident$/s|ident$|trust|" -i /var/lib/pgsql/data/pg_hba.conf
|
||||
|
||||
@ -148,22 +141,6 @@ elif [[ $PRODUCT_CHECK_UPDATE -eq $UPDATE_AVAILABLE_CODE ]]; then
|
||||
-mysqlp ${MYSQL_ROOT_PASS}
|
||||
fi
|
||||
|
||||
NGINX_ROOT_DIR="/etc/nginx"
|
||||
|
||||
NGINX_WORKER_PROCESSES=${NGINX_WORKER_PROCESSES:-$(grep processor /proc/cpuinfo | wc -l)};
|
||||
NGINX_WORKER_CONNECTIONS=${NGINX_WORKER_CONNECTIONS:-$(ulimit -n)};
|
||||
|
||||
sed 's/^worker_processes.*/'"worker_processes ${NGINX_WORKER_PROCESSES};"'/' -i ${NGINX_ROOT_DIR}/nginx.conf
|
||||
sed 's/worker_connections.*/'"worker_connections ${NGINX_WORKER_CONNECTIONS};"'/' -i ${NGINX_ROOT_DIR}/nginx.conf
|
||||
|
||||
if rpm -q "firewalld"; then
|
||||
firewall-cmd --permanent --zone=public --add-service=http
|
||||
firewall-cmd --permanent --zone=public --add-service=https
|
||||
systemctl restart firewalld.service
|
||||
fi
|
||||
|
||||
systemctl restart nginx
|
||||
|
||||
echo ""
|
||||
echo "$RES_INSTALL_SUCCESS"
|
||||
echo "$RES_QUESTIONS"
|
||||
|
@ -50,7 +50,6 @@ yum localinstall -y --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusi
|
||||
MONOREV=$REV
|
||||
if [ "$REV" = "9" ]; then
|
||||
MONOREV="8"
|
||||
yum localinstall -y --nogpgcheck https://vault.centos.org/centos/8/AppStream/x86_64/os/Packages/xorg-x11-font-utils-7.5-41.el8.x86_64.rpm
|
||||
elif [ "$REV" = "8" ]; then
|
||||
POWERTOOLS_REPO="--enablerepo=powertools"
|
||||
fi
|
||||
@ -61,6 +60,7 @@ curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.
|
||||
|
||||
#add nodejs repo
|
||||
curl -sL https://rpm.nodesource.com/setup_16.x | sed 's/centos|/'$DIST'|/g' | sudo bash - || true
|
||||
rpm --import http://rpm.nodesource.com/pub/el/NODESOURCE-GPG-SIGNING-KEY-EL
|
||||
|
||||
#add dotnet repo
|
||||
if [ $REV = "7" ] || [[ $DIST != "redhat" && $REV = "8" ]]; then
|
||||
@ -104,9 +104,6 @@ gpgkey=https://nginx.org/keys/nginx_signing.key
|
||||
module_hotfixes=true
|
||||
END
|
||||
|
||||
${package_manager} -y install python3-dnf-plugin-versionlock || ${package_manager} -y install yum-plugin-versionlock
|
||||
${package_manager} versionlock clear
|
||||
|
||||
${package_manager} -y install epel-release \
|
||||
python3 \
|
||||
nodejs \
|
||||
@ -119,7 +116,8 @@ ${package_manager} -y install epel-release \
|
||||
rabbitmq-server$rabbitmq_version \
|
||||
redis --enablerepo=remi \
|
||||
SDL2 $POWERTOOLS_REPO \
|
||||
expect
|
||||
expect \
|
||||
ffmpeg
|
||||
|
||||
py3_version=$(python3 -c 'import sys; print(sys.version_info.minor)')
|
||||
if [[ $py3_version -lt 6 ]]; then
|
||||
|
@ -219,18 +219,11 @@ set_core_machinekey () {
|
||||
}
|
||||
|
||||
install_json() {
|
||||
|
||||
if [ ! -e /usr/bin/json ]; then
|
||||
echo -n "Install json package... "
|
||||
npm i json -g >/dev/null 2>&1
|
||||
echo "OK"
|
||||
fi
|
||||
|
||||
#Creating a user-defined .json
|
||||
if [ ! -e $USER_CONF ]; then
|
||||
echo "{}" >> $USER_CONF
|
||||
chown ${PACKAGE_SYSNAME}:${PACKAGE_SYSNAME} $USER_CONF
|
||||
fi
|
||||
}
|
||||
|
||||
restart_services() {
|
||||
@ -427,6 +420,12 @@ setup_nginx(){
|
||||
rm -f $NGINX_CONF/default.conf >/dev/null 2>&1 || rm -f $NGINX_DIR/sites-enabled/default >/dev/null 2>&1
|
||||
sed -i "s/listen.*;/listen $APP_PORT;/" $NGINX_CONF/${PACKAGE_SYSNAME}.conf
|
||||
|
||||
NGINX_WORKER_PROCESSES=${NGINX_WORKER_PROCESSES:-$(grep processor /proc/cpuinfo | wc -l)};
|
||||
NGINX_WORKER_CONNECTIONS=${NGINX_WORKER_CONNECTIONS:-$(ulimit -n)};
|
||||
|
||||
sed "s!\(^worker_processes\).*;!\1 ${NGINX_WORKER_PROCESSES};!" -i ${NGINX_ROOT_DIR}/nginx.conf
|
||||
sed "s!\(worker_connections\).*;!\1 ${NGINX_WORKER_CONNECTIONS};!" -i ${NGINX_ROOT_DIR}/nginx.conf
|
||||
|
||||
if [ "$DIST" = "RedHat" ]; then
|
||||
# Remove default nginx settings
|
||||
DELETION_LINE=$(sed -n '/server {/=' /etc/nginx/nginx.conf | head -n 1)
|
||||
@ -472,7 +471,26 @@ setup_nginx(){
|
||||
true
|
||||
done
|
||||
fi
|
||||
|
||||
if rpm -q "firewalld"; then
|
||||
firewall-cmd --permanent --zone=public --add-service=http
|
||||
firewall-cmd --permanent --zone=public --add-service=https
|
||||
systemctl restart firewalld.service
|
||||
fi
|
||||
elif [ "$DIST" = "Debian" ]; then
|
||||
if ! id "nginx" &>/dev/null; then
|
||||
systemctl stop nginx
|
||||
|
||||
rm -dfr /var/log/nginx/*
|
||||
rm -dfr /var/cache/nginx/*
|
||||
useradd -s /bin/false nginx
|
||||
|
||||
systemctl start nginx
|
||||
else
|
||||
systemctl reload nginx
|
||||
fi
|
||||
fi
|
||||
|
||||
chown nginx:nginx /etc/nginx/* -R
|
||||
systemctl enable nginx >/dev/null 2>&1
|
||||
systemctl restart nginx
|
||||
@ -485,7 +503,7 @@ setup_docs() {
|
||||
local JSON_DSCONF="$JSON $DS_CONF -e"
|
||||
|
||||
#Changing the Docs port in nginx conf
|
||||
sed 's/\(listen .*:\)\([0-9]\{2,5\}\b\)\( default_server\)\?\(;\)/\1'${DS_PORT}'\3\4/' -i $NGINX_CONF/ds.conf
|
||||
sed 's/\(listen .*:\)\([0-9]\{2,5\}\b\)\( default_server\)\?\(;\)/\1'${DOCUMENT_SERVER_PORT}'\3\4/' -i $NGINX_CONF/ds.conf
|
||||
sed "0,/proxy_pass .*;/{s/proxy_pass .*;/proxy_pass http:\/\/${DOCUMENT_SERVER_HOST}:${DOCUMENT_SERVER_PORT};/}" -i $NGINX_CONF/${PACKAGE_SYSNAME}.conf
|
||||
|
||||
#Enable JWT validation for Docs
|
||||
@ -581,6 +599,11 @@ setup_redis() {
|
||||
sed "s_\(\"Host\":\).*_\1 \"${REDIS_HOST}\",_" -i $APP_DIR/redis.json
|
||||
sed "s_\(\"Port\":\).*_\1 \"${REDIS_PORT}\"_" -i $APP_DIR/redis.json
|
||||
|
||||
if [ -e /etc/redis/redis.conf ]; then
|
||||
sed "s_\(^bind\).*_\1 ${REDIS_HOST}_" -i /etc/redis/redis.conf
|
||||
sed -r "/^save\s[0-9]+/d" -i /etc/redis/redis.conf
|
||||
fi
|
||||
|
||||
systemctl enable $REDIS_PACKAGE >/dev/null 2>&1
|
||||
systemctl restart $REDIS_PACKAGE
|
||||
|
||||
@ -601,6 +624,17 @@ setup_rabbitmq() {
|
||||
product_configuration(){
|
||||
echo -n "Configuring ${PRODUCT}... "
|
||||
|
||||
#Creating environment configuration files
|
||||
enviromentFiles=("appsettings.$ENVIRONMENT.json" "apisystem.$ENVIRONMENT.json" "elastic.$ENVIRONMENT.json" "rabbitmq.$ENVIRONMENT.json")
|
||||
|
||||
for i in "${!enviromentFiles[@]}";
|
||||
do
|
||||
if [ ! -e "$APP_DIR/${enviromentFiles[$i]}" ]; then
|
||||
echo "{}" >> "$APP_DIR/${enviromentFiles[$i]}"
|
||||
chown ${PACKAGE_SYSNAME}:${PACKAGE_SYSNAME} "$APP_DIR/${enviromentFiles[$i]}"
|
||||
fi
|
||||
done
|
||||
|
||||
$JSON $APP_DIR/plugins.json -e "this.pluginsConf={'path': \"$PRODUCT_DIR/Tools/radicale/plugins/\" }" >/dev/null 2>&1
|
||||
set_core_machinekey
|
||||
|
||||
|
@ -63,6 +63,7 @@ Package: {{product}}-files-services
|
||||
Architecture: any
|
||||
Depends: {{product}}-common (= {{package_header_tag_version}}),
|
||||
dotnet-sdk-7.0,
|
||||
ffmpeg,
|
||||
${misc:Depends},
|
||||
${shlibs:Depends}
|
||||
Description: {{product}}-files-services
|
||||
|
@ -227,14 +227,12 @@ CMD ["ASC.Files.dll", "ASC.Files"]
|
||||
|
||||
## ASC.Files.Service ##
|
||||
FROM dotnetrun AS files_services
|
||||
RUN apt-get -y update && \
|
||||
apt-get install -yq ffmpeg &&\
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64
|
||||
WORKDIR ${BUILD_PATH}/products/ASC.Files/service/
|
||||
|
||||
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.py ./docker-entrypoint.py
|
||||
COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Files.Service/service/ .
|
||||
COPY --from=onlyoffice/ffvideo:6.0 --chown=onlyoffice:onlyoffice /usr/local /usr/local/
|
||||
|
||||
CMD ["ASC.Files.Service.dll", "ASC.Files.Service", "core:eventBus:subscriptionClientName=asc_event_bus_files_service_queue"]
|
||||
|
||||
|
@ -225,7 +225,6 @@ CMD ["ASC.Files.dll", "ASC.Files"]
|
||||
FROM dotnetrun AS files_services
|
||||
RUN apt-get -y update && \
|
||||
apt-get install -yq ffmpeg
|
||||
|
||||
WORKDIR ${BUILD_PATH}/products/ASC.Files/service/
|
||||
|
||||
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.py ./docker-entrypoint.py
|
||||
@ -261,13 +260,13 @@ COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Socket
|
||||
CMD ["server.js", "ASC.Socket.IO"]
|
||||
|
||||
## ASC.SsoAuth ##
|
||||
# FROM noderun AS ssoauth
|
||||
# WORKDIR ${BUILD_PATH}/services/ASC.SsoAuth/
|
||||
FROM noderun AS ssoauth
|
||||
WORKDIR ${BUILD_PATH}/services/ASC.SsoAuth/
|
||||
|
||||
# COPY --chown=onlyoffice:onlyoffice docker-entrypoint.py ./docker-entrypoint.py
|
||||
# COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.SsoAuth/service/ .
|
||||
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.py ./docker-entrypoint.py
|
||||
COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.SsoAuth/service/ .
|
||||
|
||||
# CMD ["app.js", "ASC.SsoAuth"]
|
||||
CMD ["app.js", "ASC.SsoAuth"]
|
||||
|
||||
## ASC.Studio.Notify ##
|
||||
FROM dotnetrun AS studio_notify
|
||||
|
585
build/install/docker/Dockerfile.ffvideo
Normal file
585
build/install/docker/Dockerfile.ffvideo
Normal file
@ -0,0 +1,585 @@
|
||||
FROM ubuntu:20.04 AS base
|
||||
ENV DEBIAN_FRONTEND="noninteractive"
|
||||
ENV TZ="Etc/UTC"
|
||||
|
||||
RUN apt-get -yqq update && \
|
||||
apt-get install -yq --no-install-recommends ca-certificates expat libgomp1 && \
|
||||
apt-get autoremove -y && \
|
||||
apt-get clean -y
|
||||
|
||||
FROM base as build
|
||||
|
||||
ENV FFMPEG_VERSION=6.0 \
|
||||
AOM_VERSION=v1.0.0 \
|
||||
CHROMAPRINT_VERSION=1.5.0 \
|
||||
FDKAAC_VERSION=0.1.5 \
|
||||
FONTCONFIG_VERSION=2.12.4 \
|
||||
FREETYPE_VERSION=2.10.4 \
|
||||
FRIBIDI_VERSION=0.19.7 \
|
||||
KVAZAAR_VERSION=2.0.0 \
|
||||
LAME_VERSION=3.100 \
|
||||
LIBASS_VERSION=0.13.7 \
|
||||
LIBPTHREAD_STUBS_VERSION=0.4 \
|
||||
LIBVIDSTAB_VERSION=1.1.0 \
|
||||
LIBXCB_VERSION=1.13.1 \
|
||||
XCBPROTO_VERSION=1.13 \
|
||||
OGG_VERSION=1.3.2 \
|
||||
OPENCOREAMR_VERSION=0.1.5 \
|
||||
OPUS_VERSION=1.2 \
|
||||
OPENJPEG_VERSION=2.1.2 \
|
||||
THEORA_VERSION=1.1.1 \
|
||||
VORBIS_VERSION=1.3.5 \
|
||||
VPX_VERSION=1.8.0 \
|
||||
WEBP_VERSION=1.0.2 \
|
||||
X264_VERSION=20170226-2245-stable \
|
||||
X265_VERSION=3.4 \
|
||||
XAU_VERSION=1.0.9 \
|
||||
XORG_MACROS_VERSION=1.19.2 \
|
||||
XPROTO_VERSION=7.0.31 \
|
||||
XVID_VERSION=1.3.4 \
|
||||
LIBXML2_VERSION=2.9.12 \
|
||||
LIBBLURAY_VERSION=1.1.2 \
|
||||
LIBZMQ_VERSION=4.3.2 \
|
||||
LIBSRT_VERSION=1.4.1 \
|
||||
LIBARIBB24_VERSION=1.0.3 \
|
||||
LIBPNG_VERSION=1.6.9 \
|
||||
LIBVMAF_VERSION=2.1.1 \
|
||||
SRC=/usr/local
|
||||
|
||||
ARG FREETYPE_SHA256SUM="5eab795ebb23ac77001cfb68b7d4d50b5d6c7469247b0b01b2c953269f658dac freetype-2.10.4.tar.gz"
|
||||
ARG FRIBIDI_SHA256SUM="3fc96fa9473bd31dcb5500bdf1aa78b337ba13eb8c301e7c28923fea982453a8 0.19.7.tar.gz"
|
||||
ARG LIBASS_SHA256SUM="8fadf294bf701300d4605e6f1d92929304187fca4b8d8a47889315526adbafd7 0.13.7.tar.gz"
|
||||
ARG LIBVIDSTAB_SHA256SUM="14d2a053e56edad4f397be0cb3ef8eb1ec3150404ce99a426c4eb641861dc0bb v1.1.0.tar.gz"
|
||||
ARG OGG_SHA256SUM="e19ee34711d7af328cb26287f4137e70630e7261b17cbe3cd41011d73a654692 libogg-1.3.2.tar.gz"
|
||||
ARG OPUS_SHA256SUM="77db45a87b51578fbc49555ef1b10926179861d854eb2613207dc79d9ec0a9a9 opus-1.2.tar.gz"
|
||||
ARG THEORA_SHA256SUM="40952956c47811928d1e7922cda3bc1f427eb75680c3c37249c91e949054916b libtheora-1.1.1.tar.gz"
|
||||
ARG VORBIS_SHA256SUM="6efbcecdd3e5dfbf090341b485da9d176eb250d893e3eb378c428a2db38301ce libvorbis-1.3.5.tar.gz"
|
||||
ARG XVID_SHA256SUM="4e9fd62728885855bc5007fe1be58df42e5e274497591fec37249e1052ae316f xvidcore-1.3.4.tar.gz"
|
||||
ARG LIBBLURAY_SHA256SUM="a3dd452239b100dc9da0d01b30e1692693e2a332a7d29917bf84bb10ea7c0b42 libbluray-1.1.2.tar.bz2"
|
||||
ARG LIBZMQ_SHA256SUM="02ecc88466ae38cf2c8d79f09cfd2675ba299a439680b64ade733e26a349edeb v4.3.2.tar.gz"
|
||||
ARG LIBARIBB24_SHA256SUM="f61560738926e57f9173510389634d8c06cabedfa857db4b28fb7704707ff128 v1.0.3.tar.gz"
|
||||
|
||||
|
||||
ARG LD_LIBRARY_PATH=/opt/ffmpeg/lib
|
||||
ARG MAKEFLAGS="-j2"
|
||||
ARG PKG_CONFIG_PATH="/opt/ffmpeg/share/pkgconfig:/opt/ffmpeg/lib/pkgconfig:/opt/ffmpeg/lib64/pkgconfig"
|
||||
ARG PREFIX=/opt/ffmpeg
|
||||
ARG LD_LIBRARY_PATH="/opt/ffmpeg/lib:/opt/ffmpeg/lib64"
|
||||
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN buildDeps="autoconf \
|
||||
automake \
|
||||
cmake \
|
||||
curl \
|
||||
bzip2 \
|
||||
libexpat1-dev \
|
||||
g++ \
|
||||
gcc \
|
||||
git \
|
||||
gperf \
|
||||
libtool \
|
||||
make \
|
||||
meson \
|
||||
nasm \
|
||||
perl \
|
||||
pkg-config \
|
||||
python \
|
||||
libssl-dev \
|
||||
yasm \
|
||||
zlib1g-dev" && \
|
||||
apt-get -yqq update && \
|
||||
apt-get install -yq --no-install-recommends ${buildDeps}
|
||||
## libvmaf https://github.com/Netflix/vmaf
|
||||
RUN \
|
||||
if which meson || false; then \
|
||||
echo "Building VMAF." && \
|
||||
DIR=/tmp/vmaf && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/Netflix/vmaf/archive/v${LIBVMAF_VERSION}.tar.gz && \
|
||||
tar -xz --strip-components=1 -f v${LIBVMAF_VERSION}.tar.gz && \
|
||||
cd /tmp/vmaf/libvmaf && \
|
||||
meson build --buildtype release --prefix=${PREFIX} && \
|
||||
ninja -vC build && \
|
||||
ninja -vC build install && \
|
||||
mkdir -p ${PREFIX}/share/model/ && \
|
||||
cp -r /tmp/vmaf/model/* ${PREFIX}/share/model/ && \
|
||||
rm -rf ${DIR}; \
|
||||
else \
|
||||
echo "VMAF skipped."; \
|
||||
fi
|
||||
|
||||
## opencore-amr https://sourceforge.net/projects/opencore-amr/
|
||||
RUN \
|
||||
DIR=/tmp/opencore-amr && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://sourceforge.net/projects/opencore-amr/files/opencore-amr/opencore-amr-${OPENCOREAMR_VERSION}.tar.gz/download | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## x264 http://www.videolan.org/developers/x264.html
|
||||
RUN \
|
||||
DIR=/tmp/x264 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://download.videolan.org/pub/videolan/x264/snapshots/x264-snapshot-${X264_VERSION}.tar.bz2 | \
|
||||
tar -jx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared --enable-pic --disable-cli && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### x265 http://x265.org/
|
||||
RUN \
|
||||
DIR=/tmp/x265 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://github.com/videolan/x265/archive/refs/tags/${X265_VERSION}.tar.gz | \
|
||||
tar -zx && \
|
||||
cd x265-${X265_VERSION}/build/linux && \
|
||||
sed -i "/-DEXTRA_LIB/ s/$/ -DCMAKE_INSTALL_PREFIX=\${PREFIX}/" multilib.sh && \
|
||||
sed -i "/^cmake/ s/$/ -DENABLE_CLI=OFF/" multilib.sh && \
|
||||
./multilib.sh && \
|
||||
make -C 8bit install && \
|
||||
rm -rf ${DIR}
|
||||
### libogg https://www.xiph.org/ogg/
|
||||
RUN \
|
||||
DIR=/tmp/ogg && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/ogg/libogg-${OGG_VERSION}.tar.gz && \
|
||||
echo ${OGG_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libogg-${OGG_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libopus https://www.opus-codec.org/
|
||||
RUN \
|
||||
DIR=/tmp/opus && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://archive.mozilla.org/pub/opus/opus-${OPUS_VERSION}.tar.gz && \
|
||||
echo ${OPUS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f opus-${OPUS_VERSION}.tar.gz && \
|
||||
autoreconf -fiv && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libvorbis https://xiph.org/vorbis/
|
||||
RUN \
|
||||
DIR=/tmp/vorbis && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/vorbis/libvorbis-${VORBIS_VERSION}.tar.gz && \
|
||||
echo ${VORBIS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libvorbis-${VORBIS_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --with-ogg="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libtheora http://www.theora.org/
|
||||
RUN \
|
||||
DIR=/tmp/theora && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xiph.org/releases/theora/libtheora-${THEORA_VERSION}.tar.gz && \
|
||||
echo ${THEORA_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f libtheora-${THEORA_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --with-ogg="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libvpx https://www.webmproject.org/code/
|
||||
RUN \
|
||||
DIR=/tmp/vpx && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://codeload.github.com/webmproject/libvpx/tar.gz/v${VPX_VERSION} | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-vp8 --enable-vp9 --enable-vp9-highbitdepth --enable-pic --enable-shared \
|
||||
--disable-debug --disable-examples --disable-docs --disable-install-bins && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libwebp https://developers.google.com/speed/webp/
|
||||
RUN \
|
||||
DIR=/tmp/vebp && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-${WEBP_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### libmp3lame http://lame.sourceforge.net/
|
||||
RUN \
|
||||
DIR=/tmp/lame && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://sourceforge.net/projects/lame/files/lame/${LAME_VERSION}/lame-${LAME_VERSION}.tar.gz/download | \
|
||||
tar -zx --strip-components=1 && \
|
||||
./configure --prefix="${PREFIX}" --bindir="${PREFIX}/bin" --enable-shared --enable-nasm --disable-frontend && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### xvid https://www.xvid.com/
|
||||
RUN \
|
||||
DIR=/tmp/xvid && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO http://downloads.xvid.org/downloads/xvidcore-${XVID_VERSION}.tar.gz && \
|
||||
echo ${XVID_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx -f xvidcore-${XVID_VERSION}.tar.gz && \
|
||||
cd xvidcore/build/generic && \
|
||||
./configure --prefix="${PREFIX}" --bindir="${PREFIX}/bin" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
### fdk-aac https://github.com/mstorsjo/fdk-aac
|
||||
RUN \
|
||||
DIR=/tmp/fdk-aac && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://github.com/mstorsjo/fdk-aac/archive/v${FDKAAC_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
autoreconf -fiv && \
|
||||
./configure --prefix="${PREFIX}" --enable-shared --datadir="${DIR}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## openjpeg https://github.com/uclouvain/openjpeg
|
||||
RUN \
|
||||
DIR=/tmp/openjpeg && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz | \
|
||||
tar -zx --strip-components=1 && \
|
||||
cmake -DBUILD_THIRDPARTY:BOOL=ON -DCMAKE_INSTALL_PREFIX="${PREFIX}" . && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## freetype https://www.freetype.org/
|
||||
RUN \
|
||||
DIR=/tmp/freetype && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.gz && \
|
||||
echo ${FREETYPE_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f freetype-${FREETYPE_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## libvstab https://github.com/georgmartius/vid.stab
|
||||
RUN \
|
||||
DIR=/tmp/vid.stab && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/georgmartius/vid.stab/archive/v${LIBVIDSTAB_VERSION}.tar.gz && \
|
||||
echo ${LIBVIDSTAB_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f v${LIBVIDSTAB_VERSION}.tar.gz && \
|
||||
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" . && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## fridibi https://www.fribidi.org/
|
||||
RUN \
|
||||
DIR=/tmp/fribidi && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/fribidi/fribidi/archive/${FRIBIDI_VERSION}.tar.gz && \
|
||||
echo ${FRIBIDI_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f ${FRIBIDI_VERSION}.tar.gz && \
|
||||
sed -i 's/^SUBDIRS =.*/SUBDIRS=gen.tab charset lib bin/' Makefile.am && \
|
||||
./bootstrap --no-config --auto && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make -j1 && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## fontconfig https://www.freedesktop.org/wiki/Software/fontconfig/
|
||||
RUN \
|
||||
DIR=/tmp/fontconfig && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.freedesktop.org/software/fontconfig/release/fontconfig-${FONTCONFIG_VERSION}.tar.bz2 && \
|
||||
tar -jx --strip-components=1 -f fontconfig-${FONTCONFIG_VERSION}.tar.bz2 && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## libass https://github.com/libass/libass
|
||||
RUN \
|
||||
DIR=/tmp/libass && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/libass/libass/archive/${LIBASS_VERSION}.tar.gz && \
|
||||
echo ${LIBASS_SHA256SUM} | sha256sum --check && \
|
||||
tar -zx --strip-components=1 -f ${LIBASS_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
## kvazaar https://github.com/ultravideo/kvazaar
|
||||
RUN \
|
||||
DIR=/tmp/kvazaar && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/ultravideo/kvazaar/archive/v${KVAZAAR_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f v${KVAZAAR_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/aom && \
|
||||
git clone --branch ${AOM_VERSION} --depth 1 https://aomedia.googlesource.com/aom ${DIR} ; \
|
||||
cd ${DIR} ; \
|
||||
rm -rf CMakeCache.txt CMakeFiles ; \
|
||||
mkdir -p ./aom_build ; \
|
||||
cd ./aom_build ; \
|
||||
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" -DBUILD_SHARED_LIBS=1 ..; \
|
||||
make ; \
|
||||
make install ; \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libxcb (and supporting libraries) for screen capture https://xcb.freedesktop.org/
|
||||
RUN \
|
||||
DIR=/tmp/xorg-macros && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive//individual/util/util-macros-${XORG_MACROS_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f util-macros-${XORG_MACROS_VERSION}.tar.gz && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/xproto && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive/individual/proto/xproto-${XPROTO_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f xproto-${XPROTO_VERSION}.tar.gz && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libXau && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://www.x.org/archive/individual/lib/libXau-${XAU_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libXau-${XAU_VERSION}.tar.gz && \
|
||||
./configure --srcdir=${DIR} --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libpthread-stubs && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/libpthread-stubs-${LIBPTHREAD_STUBS_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libpthread-stubs-${LIBPTHREAD_STUBS_VERSION}.tar.gz && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libxcb-proto && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/xcb-proto-${XCBPROTO_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f xcb-proto-${XCBPROTO_VERSION}.tar.gz && \
|
||||
ACLOCAL_PATH="${PREFIX}/share/aclocal" ./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
RUN \
|
||||
DIR=/tmp/libxcb && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://xcb.freedesktop.org/dist/libxcb-${LIBXCB_VERSION}.tar.gz && \
|
||||
tar -zx --strip-components=1 -f libxcb-${LIBXCB_VERSION}.tar.gz && \
|
||||
ACLOCAL_PATH="${PREFIX}/share/aclocal" ./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libxml2 - for libbluray
|
||||
RUN \
|
||||
DIR=/tmp/libxml2 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sL https://github.com/GNOME/libxml2/archive/refs/tags/v${LIBXML2_VERSION}.tar.gz | \
|
||||
tar -xz --strip-components=1 && \
|
||||
./autogen.sh --prefix="${PREFIX}" --with-ftp=no --with-http=no --with-python=no && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libbluray - Requires libxml, freetype, and fontconfig
|
||||
RUN \
|
||||
DIR=/tmp/libbluray && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://download.videolan.org/pub/videolan/libbluray/${LIBBLURAY_VERSION}/libbluray-${LIBBLURAY_VERSION}.tar.bz2 && \
|
||||
echo ${LIBBLURAY_SHA256SUM} | sha256sum --check && \
|
||||
tar -jx --strip-components=1 -f libbluray-${LIBBLURAY_VERSION}.tar.bz2 && \
|
||||
./configure --prefix="${PREFIX}" --disable-examples --disable-bdjava-jar --disable-static --enable-shared && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libzmq https://github.com/zeromq/libzmq/
|
||||
RUN \
|
||||
DIR=/tmp/libzmq && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/zeromq/libzmq/archive/v${LIBZMQ_VERSION}.tar.gz && \
|
||||
echo ${LIBZMQ_SHA256SUM} | sha256sum --check && \
|
||||
tar -xz --strip-components=1 -f v${LIBZMQ_VERSION}.tar.gz && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make check && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libsrt https://github.com/Haivision/srt
|
||||
RUN \
|
||||
DIR=/tmp/srt && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/Haivision/srt/archive/v${LIBSRT_VERSION}.tar.gz && \
|
||||
tar -xz --strip-components=1 -f v${LIBSRT_VERSION}.tar.gz && \
|
||||
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" . && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libpng
|
||||
RUN \
|
||||
DIR=/tmp/png && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
git clone https://git.code.sf.net/p/libpng/code ${DIR} -b v${LIBPNG_VERSION} --depth 1 && \
|
||||
./autogen.sh && \
|
||||
./configure --prefix="${PREFIX}" && \
|
||||
make check && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## libaribb24
|
||||
RUN \
|
||||
DIR=/tmp/b24 && \
|
||||
mkdir -p ${DIR} && \
|
||||
cd ${DIR} && \
|
||||
curl -sLO https://github.com/nkoriyama/aribb24/archive/v${LIBARIBB24_VERSION}.tar.gz && \
|
||||
echo ${LIBARIBB24_SHA256SUM} | sha256sum --check && \
|
||||
tar -xz --strip-components=1 -f v${LIBARIBB24_VERSION}.tar.gz && \
|
||||
autoreconf -fiv && \
|
||||
./configure CFLAGS="-I${PREFIX}/include -fPIC" --prefix="${PREFIX}" && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ${DIR}
|
||||
|
||||
## Download ffmpeg https://ffmpeg.org/
|
||||
RUN \
|
||||
DIR=/tmp/ffmpeg && mkdir -p ${DIR} && cd ${DIR} && \
|
||||
curl -sLO https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2 && \
|
||||
tar -jx --strip-components=1 -f ffmpeg-${FFMPEG_VERSION}.tar.bz2 && \
|
||||
./configure --disable-debug --disable-doc --disable-ffplay --enable-shared --enable-gpl --extra-libs=-ldl && \
|
||||
make ; make install
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Build ffmpeg https://ffmpeg.org/
|
||||
RUN \
|
||||
DIR=/tmp/ffmpeg && cd ${DIR} && \
|
||||
./configure \
|
||||
--disable-debug \
|
||||
--disable-doc \
|
||||
--disable-ffplay \
|
||||
--enable-fontconfig \
|
||||
--enable-gpl \
|
||||
--enable-libaom \
|
||||
--enable-libaribb24 \
|
||||
--enable-libass \
|
||||
--enable-libbluray \
|
||||
--enable-libfdk_aac \
|
||||
--enable-libfreetype \
|
||||
--enable-libkvazaar \
|
||||
--enable-libmp3lame \
|
||||
--enable-libopencore-amrnb \
|
||||
--enable-libopencore-amrwb \
|
||||
--enable-libopenjpeg \
|
||||
--enable-libopus \
|
||||
--enable-libsrt \
|
||||
--enable-libtheora \
|
||||
--enable-libvidstab \
|
||||
--enable-libvmaf \
|
||||
--enable-libvorbis \
|
||||
--enable-libvpx \
|
||||
--enable-libwebp \
|
||||
--enable-libx264 \
|
||||
--enable-libx265 \
|
||||
--enable-libxcb \
|
||||
--enable-libxvid \
|
||||
--enable-libzmq \
|
||||
--enable-nonfree \
|
||||
--enable-openssl \
|
||||
--enable-postproc \
|
||||
--enable-shared \
|
||||
--enable-small \
|
||||
--enable-version3 \
|
||||
--extra-cflags="-I${PREFIX}/include" \
|
||||
--extra-ldflags="-L${PREFIX}/lib" \
|
||||
--extra-libs=-ldl \
|
||||
--extra-libs=-lpthread \
|
||||
--prefix="${PREFIX}" && \
|
||||
make clean && \
|
||||
make && \
|
||||
make install && \
|
||||
make tools/zmqsend && cp tools/zmqsend ${PREFIX}/bin/ && \
|
||||
make distclean && \
|
||||
hash -r && \
|
||||
cd tools && \
|
||||
make qt-faststart && cp qt-faststart ${PREFIX}/bin/
|
||||
|
||||
## cleanup
|
||||
RUN \
|
||||
ldd ${PREFIX}/bin/ffmpeg | grep opt/ffmpeg | cut -d ' ' -f 3 | xargs -i cp {} /usr/local/lib/ && \
|
||||
for lib in /usr/local/lib/*.so.*; do ln -s "${lib##*/}" "${lib%%.so.*}".so; done && \
|
||||
cp ${PREFIX}/bin/* /usr/local/bin/ && \
|
||||
cp -r ${PREFIX}/share/ffmpeg /usr/local/share/ && \
|
||||
LD_LIBRARY_PATH=/usr/local/lib ffmpeg -buildconf && \
|
||||
cp -r ${PREFIX}/include/libav* ${PREFIX}/include/libpostproc ${PREFIX}/include/libsw* /usr/local/include && \
|
||||
mkdir -p /usr/local/lib/pkgconfig && \
|
||||
for pc in ${PREFIX}/lib/pkgconfig/libav*.pc ${PREFIX}/lib/pkgconfig/libpostproc.pc ${PREFIX}/lib/pkgconfig/libsw*.pc; do \
|
||||
sed "s:${PREFIX}:/usr/local:g" <"$pc" >/usr/local/lib/pkgconfig/"${pc##*/}"; \
|
||||
done
|
||||
|
||||
FROM base AS release
|
||||
ENV LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64
|
||||
|
||||
COPY --from=build /usr/local /usr/local/
|
||||
|
||||
ENTRYPOINT ["bash"]
|
@ -106,12 +106,12 @@ services:
|
||||
target: studio
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-studio:${DOCKER_TAG}"
|
||||
|
||||
# onlyoffice-ssoauth:
|
||||
# build:
|
||||
# context: ./
|
||||
# dockerfile: "${DOCKERFILE}"
|
||||
# target: ssoauth
|
||||
# image: "${REPO}/${DOCKER_IMAGE_PREFIX}-ssoauth:${DOCKER_TAG}"
|
||||
onlyoffice-ssoauth:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: "${DOCKERFILE}"
|
||||
target: ssoauth
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-ssoauth:${DOCKER_TAG}"
|
||||
|
||||
# onlyoffice-webhooks-service:
|
||||
# build:
|
||||
|
@ -129,13 +129,13 @@ services:
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-studio:${DOCKER_TAG}"
|
||||
container_name: ${STUDIO_HOST}
|
||||
|
||||
# onlyoffice-ssoauth:
|
||||
# <<: *x-service-base
|
||||
# image: "${REPO}/${DOCKER_IMAGE_PREFIX}-ssoauth:${DOCKER_TAG}"
|
||||
# container_name: ${SSOAUTH_HOST}
|
||||
# expose:
|
||||
# - ${SERVICE_PORT}
|
||||
# - "9834"
|
||||
onlyoffice-ssoauth:
|
||||
<<: *x-service-base
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-ssoauth:${DOCKER_TAG}"
|
||||
container_name: ${SSOAUTH_HOST}
|
||||
expose:
|
||||
- ${SERVICE_PORT}
|
||||
- "9834"
|
||||
|
||||
# onlyoffice-webhooks-service:
|
||||
# <<: *x-service-base
|
||||
@ -168,7 +168,7 @@ services:
|
||||
- onlyoffice-api
|
||||
# - onlyoffice-api-system
|
||||
- onlyoffice-studio
|
||||
# - onlyoffice-ssoauth
|
||||
- onlyoffice-ssoauth
|
||||
environment:
|
||||
- SERVICE_BACKUP=${SERVICE_BACKUP}
|
||||
- SERVICE_FILES=${SERVICE_FILES}
|
||||
|
@ -1,4 +1,12 @@
|
||||
version: "3.8"
|
||||
x-healthcheck:
|
||||
&x-healthcheck
|
||||
test: curl --fail http://127.0.0.1 || exit 1
|
||||
interval: 60s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
timeout: 10s
|
||||
|
||||
x-service: &x-service-base
|
||||
container_name: base
|
||||
restart: always
|
||||
@ -54,31 +62,49 @@ services:
|
||||
<<: *x-service-base
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-backup-background:${DOCKER_TAG}"
|
||||
container_name: ${BACKUP_BACKGRUOND_TASKS_HOST}
|
||||
healthcheck:
|
||||
<<: *x-healthcheck
|
||||
test: curl --fail http://${SERVICE_BACKUP_BACKGRUOND_TASKS}/health/ || exit 1
|
||||
|
||||
onlyoffice-backup:
|
||||
<<: *x-service-base
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-backup:${DOCKER_TAG}"
|
||||
container_name: ${BACKUP_HOST}
|
||||
healthcheck:
|
||||
<<: *x-healthcheck
|
||||
test: curl --fail http://${SERVICE_BACKUP}/health/ || exit 1
|
||||
|
||||
onlyoffice-clear-events:
|
||||
<<: *x-service-base
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-clear-events:${DOCKER_TAG}"
|
||||
container_name: ${CLEAR_EVENTS_HOST}
|
||||
healthcheck:
|
||||
<<: *x-healthcheck
|
||||
test: curl --fail http://${SERVICE_CLEAR_EVENTS}/health/ || exit 1
|
||||
|
||||
onlyoffice-files:
|
||||
<<: *x-service-base
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-files:${DOCKER_TAG}"
|
||||
container_name: ${FILES_HOST}
|
||||
healthcheck:
|
||||
<<: *x-healthcheck
|
||||
test: curl --fail http://${SERVICE_FILES}/health/ || exit 1
|
||||
|
||||
onlyoffice-files-services:
|
||||
<<: *x-service-base
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-files-services:${DOCKER_TAG}"
|
||||
container_name: ${FILES_SERVICES_HOST}
|
||||
healthcheck:
|
||||
<<: *x-healthcheck
|
||||
test: curl --fail http://${SERVICE_FILES_SERVICES}/health/ || exit 1
|
||||
|
||||
onlyoffice-people-server:
|
||||
<<: *x-service-base
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-people-server:${DOCKER_TAG}"
|
||||
container_name: ${PEOPLE_SERVER_HOST}
|
||||
healthcheck:
|
||||
<<: *x-healthcheck
|
||||
test: curl --fail http://${SERVICE_PEOPLE_SERVER}/health/ || exit 1
|
||||
|
||||
onlyoffice-socket:
|
||||
<<: *x-service-base
|
||||
@ -91,21 +117,33 @@ services:
|
||||
<<: *x-service-base
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-studio-notify:${DOCKER_TAG}"
|
||||
container_name: ${STUDIO_NOTIFY_HOST}
|
||||
healthcheck:
|
||||
<<: *x-healthcheck
|
||||
test: curl --fail http://${SERVICE_STUDIO_NOTIFY}/health/ || exit 1
|
||||
|
||||
onlyoffice-api:
|
||||
<<: *x-service-base
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-api:${DOCKER_TAG}"
|
||||
container_name: ${API_HOST}
|
||||
healthcheck:
|
||||
<<: *x-healthcheck
|
||||
test: curl --fail http://${SERVICE_API}/health/ || exit 1
|
||||
|
||||
onlyoffice-api-system:
|
||||
<<: *x-service-base
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-api-system:${DOCKER_TAG}"
|
||||
container_name: ${API_SYSTEM_HOST}
|
||||
healthcheck:
|
||||
<<: *x-healthcheck
|
||||
test: curl --fail http://${SERVICE_API_SYSTEM}/health/ || exit 1
|
||||
|
||||
onlyoffice-studio:
|
||||
<<: *x-service-base
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-studio:${DOCKER_TAG}"
|
||||
container_name: ${STUDIO_HOST}
|
||||
healthcheck:
|
||||
<<: *x-healthcheck
|
||||
test: curl --fail http://${SERVICE_STUDIO}/health/ || exit 1
|
||||
|
||||
onlyoffice-ssoauth:
|
||||
<<: *x-service-base
|
||||
@ -135,6 +173,9 @@ services:
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-proxy:${DOCKER_TAG}"
|
||||
container_name: ${PROXY_HOST}
|
||||
restart: always
|
||||
healthcheck:
|
||||
<<: *x-healthcheck
|
||||
test: nginx -t || exit 1
|
||||
expose:
|
||||
- "8081"
|
||||
- "8099"
|
||||
|
@ -1,4 +1,12 @@
|
||||
version: "3.8"
|
||||
x-healthcheck:
|
||||
&x-healthcheck
|
||||
test: curl --fail http://127.0.0.1 || exit 1
|
||||
interval: 60s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
timeout: 10s
|
||||
|
||||
x-service:
|
||||
&x-service-base
|
||||
container_name: base
|
||||
@ -33,6 +41,9 @@ services:
|
||||
<<: *x-service-base
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-notify:${DOCKER_TAG}"
|
||||
container_name: ${NOTIFY_HOST}
|
||||
healthcheck:
|
||||
<<: *x-healthcheck
|
||||
test: curl --fail http://${SERVICE_NOTIFY}/health/ || exit 1
|
||||
|
||||
networks:
|
||||
default:
|
||||
|
@ -18,7 +18,7 @@ Common
|
||||
Summary: Files-services
|
||||
Group: Applications/Internet
|
||||
Requires: %name-common = %version-%release
|
||||
Requires: dotnet-sdk-7.0
|
||||
Requires: dotnet-sdk-7.0, ffmpeg
|
||||
AutoReqProv: no
|
||||
%description files-services
|
||||
Files-services
|
||||
|
@ -2,4 +2,9 @@ PUSHD %~dp0..
|
||||
set dir=%~dp0..
|
||||
echo %dir%
|
||||
|
||||
dotnet test common\Tests\Frontend.Translations.Tests\Frontend.Translations.Tests.csproj --filter Name~SpellCheckTest -l:html --environment "BASE_DIR=%dir%" --results-directory "%dir%/TestsResults"
|
||||
set save=false
|
||||
|
||||
if /I "%1" == "-s" set save=%2 & shift
|
||||
shift
|
||||
|
||||
dotnet test common\Tests\Frontend.Translations.Tests\Frontend.Translations.Tests.csproj --filter Name~SpellCheckTest -l:html --environment "BASE_DIR=%dir%" --environment "SAVE=%save%" --results-directory "%dir%/TestsResults"
|
@ -3,6 +3,15 @@ echo "Run script directory:" $dir
|
||||
|
||||
dir=$(builtin cd $rd/../; pwd)
|
||||
|
||||
save=false
|
||||
|
||||
while getopts s: flag
|
||||
do
|
||||
case "${flag}" in
|
||||
s) save=${OPTARG};;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "Root directory:" $dir
|
||||
|
||||
dotnet test $dir/common/Tests/Frontend.Translations.Tests/Frontend.Translations.Tests.csproj --filter Name~SpellCheckTest -l:html --results-directory "$dir/TestsResults" --environment "BASE_DIR=$dir"
|
||||
dotnet test $dir/common/Tests/Frontend.Translations.Tests/Frontend.Translations.Tests.csproj --filter Name~SpellCheckTest -l:html --results-directory "$dir/TestsResults" --environment "BASE_DIR=$dir" --environment "SAVE=$save"
|
@ -71,7 +71,7 @@ public class Criteria : ICloneable
|
||||
/// Add nested Criteria
|
||||
/// </summary>
|
||||
/// <param name="nested"></param>
|
||||
/// <returns>себя</returns>
|
||||
/// <returns>Self</returns>
|
||||
public Criteria Add(Criteria nested)
|
||||
{
|
||||
_nestedCriteras.Add(nested);
|
||||
|
@ -417,7 +417,7 @@ public class LdapUserImporter : IDisposable
|
||||
if (!actualPortalLdapGroups.Contains(portalUserLdapGroup))
|
||||
{
|
||||
_logger.DebugTrySyncUserGroupMembershipRemovingUserFromGroup(userInfo.UserName, ldapUser.Sid, portalUserLdapGroup.Name, portalUserLdapGroup.Sid);
|
||||
UserManager.RemoveUserFromGroup(userInfo.Id, portalUserLdapGroup.ID);
|
||||
await UserManager.RemoveUserFromGroup(userInfo.Id, portalUserLdapGroup.ID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,13 +299,13 @@ public class LdapOperationJob : DistributedTaskProgress
|
||||
{
|
||||
_logger.DebugTurnOffLDAP();
|
||||
|
||||
TurnOffLDAP();
|
||||
await TurnOffLDAP();
|
||||
var ldapCurrentUserPhotos = _settingsManager.Load<LdapCurrentUserPhotos>().GetDefault();
|
||||
_settingsManager.Save(ldapCurrentUserPhotos);
|
||||
|
||||
var ldapCurrentAcccessSettings = _settingsManager.Load<LdapCurrentAcccessSettings>().GetDefault();
|
||||
_settingsManager.Save(ldapCurrentAcccessSettings);
|
||||
//не снимать права при выключении
|
||||
// don't remove permissions on shutdown
|
||||
//var rights = new List<LdapSettings.AccessRight>();
|
||||
//TakeUsersRights(rights);
|
||||
|
||||
@ -349,7 +349,7 @@ public class LdapOperationJob : DistributedTaskProgress
|
||||
: "", "");
|
||||
}
|
||||
|
||||
private void TurnOffLDAP()
|
||||
private async Task TurnOffLDAP()
|
||||
{
|
||||
const double percents = 48;
|
||||
|
||||
@ -380,7 +380,7 @@ public class LdapOperationJob : DistributedTaskProgress
|
||||
|
||||
_logger.DebugSaveUserInfo(existingLDAPUser.GetUserInfoString());
|
||||
|
||||
_userManager.UpdateUserInfo(existingLDAPUser);
|
||||
await _userManager.UpdateUserInfo(existingLDAPUser);
|
||||
break;
|
||||
case LdapOperationType.SaveTest:
|
||||
case LdapOperationType.SyncTest:
|
||||
@ -667,7 +667,7 @@ public class LdapOperationJob : DistributedTaskProgress
|
||||
|
||||
SetProgress(20, Resource.LdapSettingsStatusRemovingOldUsers, "");
|
||||
|
||||
ldapUsers = RemoveOldDbUsers(ldapUsers);
|
||||
ldapUsers = await RemoveOldDbUsers(ldapUsers);
|
||||
|
||||
SetProgress(30,
|
||||
OperationType == LdapOperationType.Save || OperationType == LdapOperationType.SaveTest
|
||||
@ -729,7 +729,7 @@ public class LdapOperationJob : DistributedTaskProgress
|
||||
|
||||
SetProgress(90, Resource.LdapSettingsStatusRemovingOldUsers, "");
|
||||
|
||||
RemoveOldDbUsers(newUniqueLdapGroupUsers);
|
||||
await RemoveOldDbUsers(newUniqueLdapGroupUsers);
|
||||
}
|
||||
|
||||
private async Task SyncDbGroups(Dictionary<GroupInfo, List<UserInfo>> ldapGroupsWithUsers)
|
||||
@ -895,7 +895,7 @@ public class LdapOperationJob : DistributedTaskProgress
|
||||
++index, count,
|
||||
_userFormatter.GetUserName(dbUser, DisplayUserNameFormat.Default)));
|
||||
|
||||
_userManager.RemoveUserFromGroup(dbUser.Id, dbLdapGroup.ID);
|
||||
await _userManager.RemoveUserFromGroup(dbUser.Id, dbLdapGroup.ID);
|
||||
}
|
||||
|
||||
index = 0;
|
||||
@ -1012,7 +1012,7 @@ public class LdapOperationJob : DistributedTaskProgress
|
||||
/// </summary>
|
||||
/// <param name="ldapUsers">list of actual LDAP users</param>
|
||||
/// <returns>New list of actual LDAP users</returns>
|
||||
private List<UserInfo> RemoveOldDbUsers(List<UserInfo> ldapUsers)
|
||||
private async Task<List<UserInfo>> RemoveOldDbUsers(List<UserInfo> ldapUsers)
|
||||
{
|
||||
var dbLdapUsers = _userManager.GetUsers(EmployeeStatus.All).Where(u => u.Sid != null).ToList();
|
||||
|
||||
@ -1064,7 +1064,7 @@ public class LdapOperationJob : DistributedTaskProgress
|
||||
|
||||
_logger.DebugSaveUserInfo(removedUser.GetUserInfoString());
|
||||
|
||||
_userManager.UpdateUserInfo(removedUser);
|
||||
await _userManager.UpdateUserInfo(removedUser);
|
||||
break;
|
||||
case LdapOperationType.SaveTest:
|
||||
case LdapOperationType.SyncTest:
|
||||
|
@ -126,7 +126,7 @@ public class LdapUserManager
|
||||
return portalUserInfo;
|
||||
}
|
||||
|
||||
if (!TryChangeExistingUserName(ldapUserInfo.UserName, onlyGetChanges))
|
||||
if (!await TryChangeExistingUserName(ldapUserInfo.UserName, onlyGetChanges))
|
||||
{
|
||||
_logger.DebugUserAlredyExistsForUserName(ldapUserInfo.Sid, ldapUserInfo.UserName);
|
||||
|
||||
@ -177,7 +177,7 @@ public class LdapUserManager
|
||||
return portalUserInfo;
|
||||
}
|
||||
|
||||
private bool TryChangeExistingUserName(string ldapUserName, bool onlyGetChanges)
|
||||
private async Task<bool> TryChangeExistingUserName(string ldapUserName, bool onlyGetChanges)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -209,7 +209,7 @@ public class LdapUserManager
|
||||
|
||||
_logger.DebugSaveUserInfo(otherUser.GetUserInfoString());
|
||||
|
||||
_userManager.UpdateUserInfo(otherUser);
|
||||
await _userManager.UpdateUserInfo(otherUser);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -343,9 +343,11 @@ public class LdapUserManager
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
_logger.DebugSyncUserLdapUpdaiting(ldapUserInfo.Sid, ldapUserInfo.UserName);
|
||||
UserInfo uf;
|
||||
if (!TryUpdateUserWithLDAPInfo(userToUpdate, ldapUserInfo, onlyGetChanges, out uf))
|
||||
_logger.DebugSyncUserLdapUpdaiting(ldapUserInfo.Sid, ldapUserInfo.UserName);
|
||||
|
||||
var (updated, uf) = await TryUpdateUserWithLDAPInfo(userToUpdate, ldapUserInfo, onlyGetChanges);
|
||||
|
||||
if (!updated)
|
||||
{
|
||||
if (onlyGetChanges)
|
||||
{
|
||||
@ -379,7 +381,7 @@ public class LdapUserManager
|
||||
|
||||
var newContacts = new List<string>(ldapUser.ContactsList);
|
||||
|
||||
for (int i = 0; i < portalUserContacts.Count; i += 2)
|
||||
for (var i = 0; i < portalUserContacts.Count; i += 2)
|
||||
{
|
||||
if (portalUserContacts[i] == EXT_MOB_PHONE || portalUserContacts[i] == EXT_MAIL
|
||||
|| portalUserContacts[i] == EXT_PHONE || portalUserContacts[i] == EXT_SKYPE)
|
||||
@ -516,9 +518,9 @@ public class LdapUserManager
|
||||
return needUpdate;
|
||||
}
|
||||
|
||||
private bool TryUpdateUserWithLDAPInfo(UserInfo userToUpdate, UserInfo updateInfo, bool onlyGetChanges, out UserInfo portlaUserInfo)
|
||||
private async Task<(bool, UserInfo)> TryUpdateUserWithLDAPInfo(UserInfo userToUpdate, UserInfo updateInfo, bool onlyGetChanges)
|
||||
{
|
||||
portlaUserInfo = Constants.LostUser;
|
||||
var portlaUserInfo = Constants.LostUser;
|
||||
|
||||
try
|
||||
{
|
||||
@ -527,11 +529,11 @@ public class LdapUserManager
|
||||
var settings = _settingsManager.Load<LdapSettings>();
|
||||
|
||||
if (!userToUpdate.UserName.Equals(updateInfo.UserName, StringComparison.InvariantCultureIgnoreCase)
|
||||
&& !TryChangeExistingUserName(updateInfo.UserName, onlyGetChanges))
|
||||
&& !await TryChangeExistingUserName(updateInfo.UserName, onlyGetChanges))
|
||||
{
|
||||
_logger.DebugUpdateUserUserNameAlredyExists(userToUpdate.Id, userToUpdate.UserName, updateInfo.UserName);
|
||||
|
||||
return false;
|
||||
return (false, portlaUserInfo);
|
||||
}
|
||||
|
||||
if (!userToUpdate.Email.Equals(updateInfo.Email, StringComparison.InvariantCultureIgnoreCase)
|
||||
@ -539,7 +541,7 @@ public class LdapUserManager
|
||||
{
|
||||
_logger.DebugUpdateUserEmailAlreadyExists(userToUpdate.Id, userToUpdate.Email, updateInfo.Email);
|
||||
|
||||
return false;
|
||||
return (false, portlaUserInfo);
|
||||
}
|
||||
|
||||
if (userToUpdate.Email != updateInfo.Email && !(updateInfo.ActivationStatus == EmployeeActivationStatus.AutoGenerated &&
|
||||
@ -589,10 +591,10 @@ public class LdapUserManager
|
||||
{
|
||||
_logger.DebugSaveUserInfo(userToUpdate.GetUserInfoString());
|
||||
|
||||
portlaUserInfo = _userManager.UpdateUserInfo(userToUpdate);
|
||||
portlaUserInfo = await _userManager.UpdateUserInfo(userToUpdate);
|
||||
}
|
||||
|
||||
return true;
|
||||
return (true, portlaUserInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -600,7 +602,7 @@ public class LdapUserManager
|
||||
userToUpdate.Sid, ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
return (false, portlaUserInfo);
|
||||
}
|
||||
|
||||
public async Task<UserInfo> TryGetAndSyncLdapUserInfo(string login, string password)
|
||||
@ -678,7 +680,7 @@ public class LdapUserManager
|
||||
log.DebugTryGetAndSyncLdapUserInfoDisablingUser(login, uInfo);
|
||||
uInfo.Status = EmployeeStatus.Terminated;
|
||||
uInfo.Sid = null;
|
||||
userManager.UpdateUserInfo(uInfo);
|
||||
await userManager.UpdateUserInfo(uInfo);
|
||||
await cookiesManager.ResetUserCookie(uInfo.Id);
|
||||
}
|
||||
}
|
||||
@ -730,7 +732,7 @@ public class LdapUserManager
|
||||
{
|
||||
userInfo.Sid = null;
|
||||
userInfo.Status = EmployeeStatus.Terminated;
|
||||
_userManager.UpdateUserInfo(userInfo);
|
||||
await _userManager.UpdateUserInfo(userInfo);
|
||||
throw new Exception("The user did not pass the configuration check by ldap group settings");
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ public class WarmupServicesStartupTask : IStartupTask
|
||||
}
|
||||
|
||||
public Task ExecuteAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
{
|
||||
var processedFailed = 0;
|
||||
var processedSuccessed = 0;
|
||||
var startTime = DateTime.UtcNow;
|
||||
@ -52,13 +52,13 @@ public class WarmupServicesStartupTask : IStartupTask
|
||||
|
||||
logger.TraceWarmupStarted();
|
||||
|
||||
tenantManager.SetCurrentTenant("localhost");
|
||||
|
||||
tenantManager.SetCurrentTenant("localhost");
|
||||
|
||||
foreach (var service in GetServices(_services))
|
||||
{
|
||||
try
|
||||
{
|
||||
scope.ServiceProvider.GetServices(service);
|
||||
{
|
||||
scope.ServiceProvider.GetService(service);
|
||||
|
||||
processedSuccessed++;
|
||||
}
|
||||
@ -72,9 +72,9 @@ public class WarmupServicesStartupTask : IStartupTask
|
||||
|
||||
var processed = processedSuccessed + processedFailed;
|
||||
|
||||
logger.TraceWarmupFinished(processed,
|
||||
processedSuccessed,
|
||||
processedFailed,
|
||||
logger.TraceWarmupFinished(processed,
|
||||
processedSuccessed,
|
||||
processedFailed,
|
||||
(DateTime.UtcNow - startTime).TotalMilliseconds);
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ public class WarmupServicesStartupTask : IStartupTask
|
||||
return services
|
||||
.Where(descriptor => descriptor.ImplementationType != typeof(WarmupServicesStartupTask))
|
||||
.Where(descriptor => descriptor.ServiceType.ContainsGenericParameters == false)
|
||||
.Select(descriptor => descriptor.ServiceType)
|
||||
.Select(descriptor => descriptor.ServiceType)
|
||||
.Distinct();
|
||||
}
|
||||
}
|
@ -146,7 +146,7 @@ public static class ServiceCollectionExtension
|
||||
var logger = sp.GetRequiredService<ILogger<DefaultActiveMQPersistentConnection>>();
|
||||
|
||||
var factory = new Apache.NMS.NMSConnectionFactory(activeMQConfiguration.Uri);
|
||||
|
||||
|
||||
var retryCount = 5;
|
||||
|
||||
if (!string.IsNullOrEmpty(cfg["core:eventBus:connectRetryCount"]))
|
||||
@ -195,10 +195,8 @@ public static class ServiceCollectionExtension
|
||||
/// Add a IHostedService for given type.
|
||||
/// Only one copy of this instance type will active in multi process architecture.
|
||||
/// </remarks>
|
||||
public static void AddActivePassiveHostedService<T>(this IServiceCollection services) where T : class, IHostedService
|
||||
public static void AddActivePassiveHostedService<T>(this IServiceCollection services, DIHelper diHelper) where T : class, IHostedService
|
||||
{
|
||||
var diHelper = new DIHelper(services);
|
||||
|
||||
diHelper.TryAdd<IRegisterInstanceDao<T>, RegisterInstanceDao<T>>();
|
||||
diHelper.TryAdd<IRegisterInstanceManager<T>, RegisterInstanceManager<T>>();
|
||||
|
||||
|
@ -70,7 +70,7 @@ public class RedisCacheNotify<T> : ICacheNotify<T> where T : IMessage<T>, new()
|
||||
|
||||
private string GetChannelName(CacheNotifyAction action)
|
||||
{
|
||||
return $"asc:channel:{action}:{typeof(T).FullName}".ToLower();
|
||||
return $"asc:channel:{action}:{typeof(T).FullName}".ToLower(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
class RedisCachePubSubItem<T0>
|
||||
|
@ -26,13 +26,6 @@
|
||||
|
||||
namespace ASC.Core.Common;
|
||||
|
||||
[Scope]
|
||||
public class CommonLinkUtilitySettings
|
||||
{
|
||||
public string ServerUri { get; set; }
|
||||
}
|
||||
|
||||
|
||||
[Scope]
|
||||
public class BaseCommonLinkUtility
|
||||
{
|
||||
@ -43,14 +36,22 @@ public class BaseCommonLinkUtility
|
||||
private string _vpath;
|
||||
|
||||
protected IHttpContextAccessor _httpContextAccessor;
|
||||
public string ServerUri
|
||||
{
|
||||
set
|
||||
{
|
||||
var uri = new Uri(value.Replace('*', 'x').Replace('+', 'x'));
|
||||
_serverRoot = new UriBuilder(uri.Scheme, uri.Host != "x" ? uri.Host : LocalHost, uri.Port);
|
||||
_vpath = "/" + uri.AbsolutePath.Trim('/');
|
||||
}
|
||||
}
|
||||
|
||||
public BaseCommonLinkUtility(
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
TenantManager tenantManager,
|
||||
ILoggerProvider options,
|
||||
CommonLinkUtilitySettings settings)
|
||||
: this(null, coreBaseSettings, coreSettings, tenantManager, options, settings)
|
||||
ILoggerProvider options)
|
||||
: this(null, coreBaseSettings, coreSettings, tenantManager, options)
|
||||
{
|
||||
}
|
||||
|
||||
@ -59,37 +60,29 @@ public class BaseCommonLinkUtility
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
TenantManager tenantManager,
|
||||
ILoggerProvider options,
|
||||
CommonLinkUtilitySettings settings)
|
||||
ILoggerProvider options)
|
||||
{
|
||||
var serverUri = settings.ServerUri;
|
||||
|
||||
if (!string.IsNullOrEmpty(serverUri))
|
||||
try
|
||||
{
|
||||
var uri = new Uri(serverUri.Replace('*', 'x').Replace('+', 'x'));
|
||||
_serverRoot = new UriBuilder(uri.Scheme, uri.Host != "x" ? uri.Host : LocalHost, uri.Port);
|
||||
_vpath = "/" + uri.AbsolutePath.Trim('/');
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
|
||||
if (_httpContextAccessor?.HttpContext?.Request != null)
|
||||
{
|
||||
var u = _httpContextAccessor?.HttpContext.Request.GetUrlRewriter();
|
||||
|
||||
ArgumentNullException.ThrowIfNull(u);
|
||||
|
||||
_serverRoot = new UriBuilder(u.Scheme, LocalHost, u.Port);
|
||||
}
|
||||
else if (_serverRoot == null)
|
||||
{
|
||||
_serverRoot = new UriBuilder(Uri.UriSchemeHttp, LocalHost);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception error)
|
||||
{
|
||||
try
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
var uriBuilder = new UriBuilder(Uri.UriSchemeHttp, LocalHost);
|
||||
if (_httpContextAccessor?.HttpContext?.Request != null)
|
||||
{
|
||||
var u = _httpContextAccessor?.HttpContext.Request.GetUrlRewriter();
|
||||
|
||||
ArgumentNullException.ThrowIfNull(u);
|
||||
|
||||
uriBuilder = new UriBuilder(u.Scheme, LocalHost, u.Port);
|
||||
}
|
||||
_serverRoot = uriBuilder;
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
options.CreateLogger("ASC.Web").ErrorWithException(error);
|
||||
}
|
||||
options.CreateLogger("ASC.Web").ErrorWithException(error);
|
||||
}
|
||||
|
||||
_coreBaseSettings = coreBaseSettings;
|
||||
@ -103,16 +96,10 @@ public class BaseCommonLinkUtility
|
||||
private readonly CoreSettings _coreSettings;
|
||||
protected TenantManager _tenantManager;
|
||||
|
||||
private string _serverRootPath;
|
||||
public string ServerRootPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_serverRootPath))
|
||||
{
|
||||
return _serverRootPath;
|
||||
}
|
||||
|
||||
UriBuilder result;
|
||||
// first, take from current request
|
||||
if (_httpContextAccessor?.HttpContext?.Request != null)
|
||||
@ -160,7 +147,7 @@ public class BaseCommonLinkUtility
|
||||
}
|
||||
}
|
||||
|
||||
return _serverRootPath = result.Uri.ToString().TrimEnd('/');
|
||||
return result.Uri.ToString().TrimEnd('/');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ public interface ITariffService
|
||||
{
|
||||
IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds);
|
||||
IEnumerable<PaymentInfo> GetPayments(int tenantId);
|
||||
Tariff GetTariff(int tenantId, bool withRequestToPaymentSystem = true);
|
||||
Tariff GetTariff(int tenantId, bool withRequestToPaymentSystem = true, bool refresh = false);
|
||||
Task<Uri> GetShoppingUri(int tenant, string currency = null, string language = null, string customerEmail = null, Dictionary<string, int> quantity = null, string backUrl = null);
|
||||
Uri GetShoppingUri(int? tenant, int quotaId, string affiliateId, string currency = null, string language = null, string customerId = null, string quantity = null);
|
||||
Uri GetShoppingUri(string[] productIds, string affiliateId = null, string currency = null, string language = null, string customerId = null, string quantity = null);
|
||||
|
@ -53,7 +53,7 @@ public class Tariff
|
||||
return t != null
|
||||
&& t.DueDate == DueDate
|
||||
&& t.Quotas.Count == Quotas.Count
|
||||
&& t.Quotas.Any(q => Quotas.Contains(q))
|
||||
&& t.Quotas.Any(Quotas.Contains)
|
||||
&& t.CustomerId == CustomerId;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// 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
|
||||
|
||||
|
||||
namespace ASC.Core.Billing;
|
||||
|
||||
[Singletone]
|
||||
@ -145,18 +145,9 @@ public class TariffService : ITariffService
|
||||
_cache = _tariffServiceStorage.Cache;
|
||||
_notify = _tariffServiceStorage.Notify;
|
||||
_dbContextFactory = coreDbContextManager;
|
||||
//var range = (_configuration["core.payment-user-range"] ?? "").Split('-');
|
||||
//if (!int.TryParse(range[0], out _activeUsersMin))
|
||||
//{
|
||||
// _activeUsersMin = 0;
|
||||
//}
|
||||
//if (range.Length < 2 || !int.TryParse(range[1], out _activeUsersMax))
|
||||
//{
|
||||
// _activeUsersMax = constants.MaxEveryoneCount;
|
||||
//}
|
||||
}
|
||||
|
||||
public Tariff GetTariff(int tenantId, bool withRequestToPaymentSystem = true)
|
||||
public Tariff GetTariff(int tenantId, bool withRequestToPaymentSystem = true, bool refresh = false)
|
||||
{
|
||||
//single tariff for all portals
|
||||
if (_coreBaseSettings.Standalone)
|
||||
@ -164,8 +155,7 @@ public class TariffService : ITariffService
|
||||
tenantId = -1;
|
||||
}
|
||||
|
||||
var tariff = GetTariffFromCache(tenantId);
|
||||
int? tariffId = null;
|
||||
var tariff = refresh ? null : GetTariffFromCache(tenantId);
|
||||
|
||||
if (tariff == null)
|
||||
{
|
||||
@ -174,11 +164,12 @@ public class TariffService : ITariffService
|
||||
|
||||
if (string.IsNullOrEmpty(_cache.Get<string>(GetTariffNeedToUpdateCacheKey(tenantId))))
|
||||
{
|
||||
tariffId = tariff.Id;
|
||||
UpdateCache(tariff.Id);
|
||||
}
|
||||
|
||||
if (_billingClient.Configured && withRequestToPaymentSystem)
|
||||
{
|
||||
var paymentFound = false;
|
||||
|
||||
try
|
||||
{
|
||||
@ -190,10 +181,11 @@ public class TariffService : ITariffService
|
||||
|
||||
var asynctariff = CreateDefault(true);
|
||||
string email = null;
|
||||
var tenantQuotas = _quotaService.GetTenantQuotas();
|
||||
|
||||
foreach (var currentPayment in currentPayments)
|
||||
foreach (var currentPayment in currentPayments.OrderBy(r => r.EndDate))
|
||||
{
|
||||
var quota = _quotaService.GetTenantQuotas().SingleOrDefault(q => q.ProductId == currentPayment.ProductId.ToString());
|
||||
var quota = tenantQuotas.SingleOrDefault(q => q.ProductId == currentPayment.ProductId.ToString());
|
||||
if (quota == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Quota with id {currentPayment.ProductId} not found for portal {GetPortalId(tenantId)}.");
|
||||
@ -204,10 +196,23 @@ public class TariffService : ITariffService
|
||||
var paymentEndDate = 9999 <= currentPayment.EndDate.Year ? DateTime.MaxValue : currentPayment.EndDate;
|
||||
asynctariff.DueDate = DateTime.Compare(asynctariff.DueDate, paymentEndDate) < 0 ? asynctariff.DueDate : paymentEndDate;
|
||||
|
||||
asynctariff.Quotas = asynctariff.Quotas.Where(r => r.Id != quota.Tenant).ToList();
|
||||
asynctariff.Quotas.Add(new Quota(quota.Tenant, currentPayment.Quantity));
|
||||
email = currentPayment.PaymentEmail;
|
||||
}
|
||||
|
||||
TenantQuota updatedQuota = null;
|
||||
|
||||
foreach (var quota in asynctariff.Quotas)
|
||||
{
|
||||
var tenantQuota = tenantQuotas.SingleOrDefault(q => q.Tenant == quota.Id);
|
||||
|
||||
tenantQuota *= quota.Quantity;
|
||||
updatedQuota += tenantQuota;
|
||||
}
|
||||
|
||||
updatedQuota.Check(_serviceProvider).Wait();
|
||||
|
||||
if (!string.IsNullOrEmpty(email))
|
||||
{
|
||||
asynctariff.CustomerId = email;
|
||||
@ -217,10 +222,21 @@ public class TariffService : ITariffService
|
||||
{
|
||||
asynctariff = CalculateTariff(tenantId, asynctariff);
|
||||
tariff = asynctariff;
|
||||
tariffId = asynctariff.Id;
|
||||
}
|
||||
|
||||
UpdateCache(tariff.Id);
|
||||
|
||||
paymentFound = true;
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
if (error is not BillingNotFoundException)
|
||||
{
|
||||
LogError(error, tenantId.ToString());
|
||||
}
|
||||
}
|
||||
catch (BillingNotFoundException)
|
||||
|
||||
if (!paymentFound)
|
||||
{
|
||||
var freeTariff = tariff.Quotas.FirstOrDefault(tariffRow =>
|
||||
{
|
||||
@ -244,22 +260,23 @@ public class TariffService : ITariffService
|
||||
{
|
||||
asynctariff = CalculateTariff(tenantId, asynctariff);
|
||||
tariff = asynctariff;
|
||||
tariffId = asynctariff.Id;
|
||||
}
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
LogError(error, tenantId.ToString());
|
||||
|
||||
UpdateCache(tariff.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tariffId.HasValue && tariffId.Value != 0)
|
||||
else
|
||||
{
|
||||
_notify.Publish(new TariffCacheItem { TenantId = tenantId, TariffId = tariffId.Value }, CacheNotifyAction.Insert);
|
||||
tariff = CalculateTariff(tenantId, tariff);
|
||||
}
|
||||
|
||||
return tariff;
|
||||
|
||||
void UpdateCache(int tariffId)
|
||||
{
|
||||
_notify.Publish(new TariffCacheItem { TenantId = tenantId, TariffId = tariffId }, CacheNotifyAction.Insert);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> PaymentChange(int tenantId, Dictionary<string, int> quantity)
|
||||
@ -430,6 +447,27 @@ public class TariffService : ITariffService
|
||||
|
||||
public async Task<Uri> GetShoppingUri(int tenant, string currency = null, string language = null, string customerEmail = null, Dictionary<string, int> quantity = null, string backUrl = null)
|
||||
{
|
||||
List<TenantQuota> newQuotas = new();
|
||||
|
||||
if (_billingClient.Configured)
|
||||
{
|
||||
var allQuotas = _quotaService.GetTenantQuotas().Where(q => !string.IsNullOrEmpty(q.ProductId) && q.Visible).ToList();
|
||||
newQuotas = quantity.Select(item => allQuotas.FirstOrDefault(q => q.Name == item.Key)).ToList();
|
||||
|
||||
TenantQuota updatedQuota = null;
|
||||
foreach (var addedQuota in newQuotas)
|
||||
{
|
||||
var qty = quantity[addedQuota.Name];
|
||||
|
||||
var quota = addedQuota;
|
||||
|
||||
quota *= qty;
|
||||
updatedQuota += quota;
|
||||
}
|
||||
|
||||
await updatedQuota.Check(_serviceProvider);
|
||||
}
|
||||
|
||||
var hasQuantity = quantity != null && quantity.Any();
|
||||
var key = "shopingurl_" + (hasQuantity ? string.Join('_', quantity.Keys.ToArray()) : "all");
|
||||
var url = _cache.Get<string>(key);
|
||||
@ -438,22 +476,6 @@ public class TariffService : ITariffService
|
||||
url = string.Empty;
|
||||
if (_billingClient.Configured)
|
||||
{
|
||||
var allQuotas = _quotaService.GetTenantQuotas().Where(q => !string.IsNullOrEmpty(q.ProductId) && q.Visible);
|
||||
var newQuotas = quantity.Select(item => allQuotas.FirstOrDefault(q => q.Name == item.Key));
|
||||
|
||||
TenantQuota updatedQuota = null;
|
||||
foreach (var addedQuota in newQuotas)
|
||||
{
|
||||
var qty = quantity[addedQuota.Name];
|
||||
|
||||
var quota = addedQuota;
|
||||
|
||||
quota *= qty;
|
||||
updatedQuota += quota;
|
||||
}
|
||||
|
||||
await updatedQuota.Check(_serviceProvider);
|
||||
|
||||
var productIds = newQuotas.Select(q => q.ProductId);
|
||||
|
||||
try
|
||||
@ -682,6 +704,7 @@ public class TariffService : ITariffService
|
||||
}
|
||||
|
||||
var tariff = CreateDefault(true);
|
||||
tariff.Id = r.Id;
|
||||
tariff.DueDate = r.Stamp.Year < 9999 ? r.Stamp : DateTime.MaxValue;
|
||||
tariff.CustomerId = r.CustomerId;
|
||||
|
||||
@ -727,6 +750,7 @@ public class TariffService : ITariffService
|
||||
if (efTariff.Id == default)
|
||||
{
|
||||
efTariff.Id = (-tenant);
|
||||
tariffInfo.Id = efTariff.Id;
|
||||
}
|
||||
|
||||
if (efTariff.CustomerId == default)
|
||||
@ -769,8 +793,9 @@ public class TariffService : ITariffService
|
||||
// update tenant.LastModified to flush cache in documents
|
||||
_tenantService.SaveTenant(_coreSettings, t);
|
||||
}
|
||||
|
||||
ClearCache(tenant);
|
||||
|
||||
NotifyWebSocket(currentTariff, tariffInfo);
|
||||
}
|
||||
|
||||
return inserted;
|
||||
@ -941,6 +966,57 @@ public class TariffService : ITariffService
|
||||
}
|
||||
}
|
||||
|
||||
private void NotifyWebSocket(Tariff currenTariff, Tariff newTariff)
|
||||
{
|
||||
var quotaSocketManager = _serviceProvider.GetRequiredService<QuotaSocketManager>();
|
||||
|
||||
var updatedQuota = GetTenantQuotaFromTariff(newTariff);
|
||||
|
||||
var maxTotalSize = updatedQuota.MaxTotalSize;
|
||||
var maxTotalSizeFeatureName = updatedQuota.GetFeature<MaxTotalSizeFeature>().Name;
|
||||
|
||||
_ = quotaSocketManager.ChangeQuotaFeatureValue(maxTotalSizeFeatureName, maxTotalSize);
|
||||
|
||||
var maxPaidUsers = updatedQuota.CountRoomAdmin;
|
||||
var maxPaidUsersFeatureName = updatedQuota.GetFeature<CountPaidUserFeature>().Name;
|
||||
|
||||
_ = quotaSocketManager.ChangeQuotaFeatureValue(maxPaidUsersFeatureName, maxPaidUsers);
|
||||
|
||||
var maxRoomCount = updatedQuota.CountRoom == int.MaxValue ? -1 : updatedQuota.CountRoom;
|
||||
var maxRoomCountFeatureName = updatedQuota.GetFeature<CountRoomFeature>().Name;
|
||||
|
||||
_ = quotaSocketManager.ChangeQuotaFeatureValue(maxRoomCountFeatureName, maxRoomCount);
|
||||
|
||||
if (currenTariff != null)
|
||||
{
|
||||
var currentQuota = GetTenantQuotaFromTariff(currenTariff);
|
||||
|
||||
var free = updatedQuota.Free;
|
||||
if (currentQuota.Free != free)
|
||||
{
|
||||
var freeFeatureName = updatedQuota.GetFeature<FreeFeature>().Name;
|
||||
|
||||
_ = quotaSocketManager.ChangeQuotaFeatureValue(freeFeatureName, free);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TenantQuota GetTenantQuotaFromTariff(Tariff tariff)
|
||||
{
|
||||
TenantQuota result = null;
|
||||
foreach (var tariffRow in tariff.Quotas)
|
||||
{
|
||||
var qty = tariffRow.Quantity;
|
||||
|
||||
var quota = _quotaService.GetTenantQuota(tariffRow.Id);
|
||||
|
||||
quota *= qty;
|
||||
result += quota;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public int GetPaymentDelay()
|
||||
{
|
||||
return _paymentDelay;
|
||||
|
@ -271,6 +271,7 @@ public class CachedUserService : IUserService, ICachedService
|
||||
{
|
||||
Service.SetUserPhoto(tenant, id, photo);
|
||||
CacheUserPhotoItem.Publish(new UserPhotoCacheItem { Key = UserServiceCache.GetUserPhotoCacheKey(tenant, id) }, CacheNotifyAction.Remove);
|
||||
CacheUserInfoItem.Publish(new UserInfoCacheItem { Id = id.ToString(), Tenant = tenant }, CacheNotifyAction.Any);
|
||||
}
|
||||
|
||||
public DateTime GetUserPasswordStamp(int tenant, Guid id)
|
||||
|
@ -45,7 +45,7 @@ public class TenantManager
|
||||
internal CoreBaseSettings CoreBaseSettings { get; set; }
|
||||
internal CoreSettings CoreSettings { get; set; }
|
||||
|
||||
private readonly static object _lock = new object();
|
||||
private static readonly object _lock = new object();
|
||||
|
||||
static TenantManager()
|
||||
{
|
||||
@ -283,17 +283,17 @@ public class TenantManager
|
||||
return QuotaService.GetTenantQuotas().Where(q => q.Tenant < 0 && (all || q.Visible)).OrderByDescending(q => q.Tenant).ToList();
|
||||
}
|
||||
|
||||
public TenantQuota GetCurrentTenantQuota()
|
||||
public TenantQuota GetCurrentTenantQuota(bool refresh = false)
|
||||
{
|
||||
return GetTenantQuota(GetCurrentTenant().Id);
|
||||
return GetTenantQuota(GetCurrentTenant().Id, refresh);
|
||||
}
|
||||
|
||||
public TenantQuota GetTenantQuota(int tenant)
|
||||
public TenantQuota GetTenantQuota(int tenant, bool refresh = false)
|
||||
{
|
||||
var defaultQuota = QuotaService.GetTenantQuota(tenant) ?? QuotaService.GetTenantQuota(Tenant.DefaultTenant) ?? TenantQuota.Default;
|
||||
if (defaultQuota.Tenant != tenant && TariffService != null)
|
||||
{
|
||||
var tariff = TariffService.GetTariff(tenant);
|
||||
var tariff = TariffService.GetTariff(tenant, refresh: refresh);
|
||||
|
||||
TenantQuota currentQuota = null;
|
||||
foreach (var tariffRow in tariff.Quotas)
|
||||
|
@ -65,9 +65,9 @@ public class UserManager
|
||||
private readonly TenantQuotaFeatureCheckerCount<CountUserFeature> _activeUsersFeatureChecker;
|
||||
private readonly Constants _constants;
|
||||
private readonly UserFormatter _userFormatter;
|
||||
|
||||
private Tenant _tenant;
|
||||
private Tenant Tenant => _tenant ??= _tenantManager.GetCurrentTenant();
|
||||
private readonly QuotaSocketManager _quotaSocketManager;
|
||||
private readonly TenantQuotaFeatureStatHelper _tenantQuotaFeatureStatHelper;
|
||||
private Tenant Tenant => _tenantManager.GetCurrentTenant();
|
||||
|
||||
public UserManager()
|
||||
{
|
||||
@ -88,7 +88,9 @@ public class UserManager
|
||||
ICache cache,
|
||||
TenantQuotaFeatureCheckerCount<CountPaidUserFeature> countPaidUserChecker,
|
||||
TenantQuotaFeatureCheckerCount<CountUserFeature> activeUsersFeatureChecker,
|
||||
UserFormatter userFormatter
|
||||
UserFormatter userFormatter,
|
||||
QuotaSocketManager quotaSocketManager,
|
||||
TenantQuotaFeatureStatHelper tenantQuotaFeatureStatHelper
|
||||
)
|
||||
{
|
||||
_userService = service;
|
||||
@ -106,6 +108,8 @@ public class UserManager
|
||||
_activeUsersFeatureChecker = activeUsersFeatureChecker;
|
||||
_constants = _userManagerConstants.Constants;
|
||||
_userFormatter = userFormatter;
|
||||
_quotaSocketManager = quotaSocketManager;
|
||||
_tenantQuotaFeatureStatHelper = tenantQuotaFeatureStatHelper;
|
||||
}
|
||||
|
||||
public UserManager(
|
||||
@ -123,8 +127,10 @@ public class UserManager
|
||||
TenantQuotaFeatureCheckerCount<CountPaidUserFeature> tenantQuotaFeatureChecker,
|
||||
TenantQuotaFeatureCheckerCount<CountUserFeature> activeUsersFeatureChecker,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
UserFormatter userFormatter)
|
||||
: this(service, tenantManager, permissionContext, userManagerConstants, coreBaseSettings, coreSettings, instanceCrypto, radicaleClient, cardDavAddressbook, log, cache, tenantQuotaFeatureChecker, activeUsersFeatureChecker, userFormatter)
|
||||
UserFormatter userFormatter,
|
||||
QuotaSocketManager quotaSocketManager,
|
||||
TenantQuotaFeatureStatHelper tenantQuotaFeatureStatHelper)
|
||||
: this(service, tenantManager, permissionContext, userManagerConstants, coreBaseSettings, coreSettings, instanceCrypto, radicaleClient, cardDavAddressbook, log, cache, tenantQuotaFeatureChecker, activeUsersFeatureChecker, userFormatter, quotaSocketManager, tenantQuotaFeatureStatHelper)
|
||||
{
|
||||
_accessor = httpContextAccessor;
|
||||
}
|
||||
@ -322,7 +328,7 @@ public class UserManager
|
||||
return findUsers.ToArray();
|
||||
}
|
||||
|
||||
public UserInfo UpdateUserInfo(UserInfo u)
|
||||
public async Task<UserInfo> UpdateUserInfo(UserInfo u)
|
||||
{
|
||||
if (IsSystemUser(u.Id))
|
||||
{
|
||||
@ -343,15 +349,31 @@ public class UserManager
|
||||
throw new InvalidOperationException("User not found.");
|
||||
}
|
||||
|
||||
return _userService.SaveUser(_tenantManager.GetCurrentTenant().Id, u);
|
||||
var (name, value) = ("", -1);
|
||||
|
||||
if (!IsUserInGroup(oldUserData.Id, Constants.GroupUser.ID) &&
|
||||
oldUserData.Status != u.Status)
|
||||
{
|
||||
(name, value) = await _tenantQuotaFeatureStatHelper.GetStat<CountPaidUserFeature, int>();
|
||||
value = oldUserData.Status > u.Status ? ++value : --value;//crutch: data race
|
||||
}
|
||||
|
||||
var newUserData = _userService.SaveUser(_tenantManager.GetCurrentTenant().Id, u);
|
||||
|
||||
if (value > 0)
|
||||
{
|
||||
_ = _quotaSocketManager.ChangeQuotaUsedValue(name, value);
|
||||
}
|
||||
|
||||
return newUserData;
|
||||
}
|
||||
|
||||
public async Task<UserInfo> UpdateUserInfoWithSyncCardDavAsync(UserInfo u)
|
||||
{
|
||||
var oldUserData = _userService.GetUserByUserName(_tenantManager.GetCurrentTenant().Id, u.UserName);
|
||||
|
||||
var newUser = UpdateUserInfo(u);
|
||||
|
||||
var newUser = await UpdateUserInfo(u);
|
||||
|
||||
if (_coreBaseSettings.DisableDocSpace)
|
||||
{
|
||||
await SyncCardDavAsync(u, oldUserData, newUser);
|
||||
@ -644,7 +666,7 @@ public class UserManager
|
||||
return GetUsers(employeeStatus).Where(u => IsUserInGroupInternal(u.Id, groupId, refs)).ToArray();
|
||||
}
|
||||
|
||||
public async Task AddUserIntoGroup(Guid userId, Guid groupId, bool dontClearAddressBook = false)
|
||||
public async Task AddUserIntoGroup(Guid userId, Guid groupId, bool dontClearAddressBook = false, bool notifyWebSocket = true)
|
||||
{
|
||||
if (Constants.LostUser.Id == userId || Constants.LostGroupInfo.ID == groupId)
|
||||
{
|
||||
@ -652,6 +674,8 @@ public class UserManager
|
||||
}
|
||||
|
||||
var user = GetUsers(userId);
|
||||
var isUser = this.IsUser(user);
|
||||
var isPaidUser = IsPaidUser(user);
|
||||
|
||||
_permissionContext.DemandPermissions(new UserGroupObject(new UserAccount(user, _tenantManager.GetCurrentTenant().Id, _userFormatter), groupId),
|
||||
Constants.Action_EditGroups);
|
||||
@ -659,6 +683,7 @@ public class UserManager
|
||||
_userService.SaveUserGroupRef(Tenant.Id, new UserGroupRef(userId, groupId, UserGroupRefType.Contains));
|
||||
|
||||
ResetGroupCache(userId);
|
||||
|
||||
if (groupId == Constants.GroupUser.ID)
|
||||
{
|
||||
var tenant = _tenantManager.GetCurrentTenant();
|
||||
@ -671,9 +696,21 @@ public class UserManager
|
||||
await _cardDavAddressbook.Delete(myUri, user.Id, user.Email, tenant.Id);
|
||||
}
|
||||
}
|
||||
|
||||
if (!notifyWebSocket)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isUser && groupId != Constants.GroupUser.ID ||
|
||||
!isUser && !isPaidUser && groupId != Constants.GroupUser.ID)
|
||||
{
|
||||
var (name, value) = await _tenantQuotaFeatureStatHelper.GetStat<CountPaidUserFeature, int>();
|
||||
_ = _quotaSocketManager.ChangeQuotaUsedValue(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveUserFromGroup(Guid userId, Guid groupId)
|
||||
public async Task RemoveUserFromGroup(Guid userId, Guid groupId)
|
||||
{
|
||||
if (Constants.LostUser.Id == userId || Constants.LostGroupInfo.ID == groupId)
|
||||
{
|
||||
@ -681,6 +718,8 @@ public class UserManager
|
||||
}
|
||||
|
||||
var user = GetUsers(userId);
|
||||
var isUserBefore = this.IsUser(user);
|
||||
var isPaidUserBefore = IsPaidUser(user);
|
||||
|
||||
_permissionContext.DemandPermissions(new UserGroupObject(new UserAccount(user, _tenantManager.GetCurrentTenant().Id, _userFormatter), groupId),
|
||||
Constants.Action_EditGroups);
|
||||
@ -688,6 +727,16 @@ public class UserManager
|
||||
_userService.RemoveUserGroupRef(Tenant.Id, userId, groupId, UserGroupRefType.Contains);
|
||||
|
||||
ResetGroupCache(userId);
|
||||
|
||||
var isUserAfter = this.IsUser(user);
|
||||
var isPaidUserAfter = IsPaidUser(user);
|
||||
|
||||
if (isPaidUserBefore && !isPaidUserAfter && isUserAfter ||
|
||||
isUserBefore && !isUserAfter)
|
||||
{
|
||||
var (name, value) = await _tenantQuotaFeatureStatHelper.GetStat<CountPaidUserFeature, int>();
|
||||
_ = _quotaSocketManager.ChangeQuotaUsedValue(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
internal void ResetGroupCache(Guid userID)
|
||||
@ -904,7 +953,7 @@ public class UserManager
|
||||
{
|
||||
return isCollaborator;
|
||||
}
|
||||
|
||||
|
||||
if (groupId == Constants.GroupManager.ID)
|
||||
{
|
||||
return !isUser && !isCollaborator;
|
||||
@ -930,4 +979,9 @@ public class UserManager
|
||||
Sid = g.Sid
|
||||
};
|
||||
}
|
||||
|
||||
private bool IsPaidUser(UserInfo userInfo)
|
||||
{
|
||||
return this.IsCollaborator(userInfo) || this.IsDocSpaceAdmin(userInfo);
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ public class WorkContext
|
||||
INotifySender emailSender = _notifyServiceSender;
|
||||
INotifySender telegramSender = _telegramSender;
|
||||
INotifySender pushSender = _pushSender;
|
||||
|
||||
|
||||
|
||||
var postman = _configuration["core:notify:postman"];
|
||||
|
||||
@ -161,6 +161,11 @@ public class WorkContext
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterSendMethod(Func<DateTime, Task> method, string cron)
|
||||
{
|
||||
NotifyEngine.RegisterSendMethod(method, cron);
|
||||
}
|
||||
|
||||
public void RegisterSendMethod(Action<DateTime> method, string cron)
|
||||
{
|
||||
NotifyEngine.RegisterSendMethod(method, cron);
|
||||
|
@ -24,6 +24,10 @@
|
||||
// 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 ASC.Core.Common.EF;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace ASC.Core.Data;
|
||||
|
||||
[Scope]
|
||||
@ -227,7 +231,7 @@ public class EFUserService : IUserService
|
||||
if (sortBy == "type")
|
||||
{
|
||||
var q1 = from user in q
|
||||
join userGroup in userDbContext.UserGroups.Where(g => !g.Removed && (g.UserGroupId == Users.Constants.GroupAdmin.ID || g.UserGroupId == Users.Constants.GroupUser.ID
|
||||
join userGroup in userDbContext.UserGroups.Where(g => !g.Removed && (g.UserGroupId == Users.Constants.GroupAdmin.ID || g.UserGroupId == Users.Constants.GroupUser.ID
|
||||
|| g.UserGroupId == Users.Constants.GroupCollaborator.ID))
|
||||
on user.Id equals userGroup.Userid into joinedGroup
|
||||
from @group in joinedGroup.DefaultIfEmpty()
|
||||
@ -317,8 +321,8 @@ public class EFUserService : IUserService
|
||||
|
||||
if (immediate)
|
||||
{
|
||||
await userGroups.ExecuteDeleteAsync();
|
||||
await groups.ExecuteDeleteAsync();
|
||||
await userGroups.ExecuteDeleteAsync();
|
||||
await groups.ExecuteDeleteAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -372,15 +376,15 @@ public class EFUserService : IUserService
|
||||
.SetProperty(p => p.Removed, true)
|
||||
.SetProperty(p => p.LastModified, DateTime.UtcNow));
|
||||
|
||||
await users.ExecuteUpdateAsync(ug => ug
|
||||
.SetProperty(p => p.Removed, true)
|
||||
.SetProperty(p => p.LastModified, DateTime.UtcNow)
|
||||
.SetProperty(p => p.TerminatedDate, DateTime.UtcNow)
|
||||
.SetProperty(p => p.Status, EmployeeStatus.Terminated)
|
||||
);
|
||||
await users.ExecuteUpdateAsync(ug => ug
|
||||
.SetProperty(p => p.Removed, true)
|
||||
.SetProperty(p => p.LastModified, DateTime.UtcNow)
|
||||
.SetProperty(p => p.TerminatedDate, DateTime.UtcNow)
|
||||
.SetProperty(p => p.Status, EmployeeStatus.Terminated)
|
||||
);
|
||||
}
|
||||
|
||||
await tr.CommitAsync();
|
||||
await tr.CommitAsync();
|
||||
}).GetAwaiter()
|
||||
.GetResult();
|
||||
}
|
||||
@ -403,7 +407,7 @@ public class EFUserService : IUserService
|
||||
var userGroups = userDbContext.UserGroups.Where(r => r.Tenant == tenant && r.Userid == userId && r.UserGroupId == groupId && r.RefType == refType);
|
||||
if (immediate)
|
||||
{
|
||||
await userGroups.ExecuteDeleteAsync();
|
||||
await userGroups.ExecuteDeleteAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -517,7 +521,7 @@ public class EFUserService : IUserService
|
||||
if (user != null)
|
||||
{
|
||||
user.LastModified = userGroupRef.LastModified;
|
||||
await userDbContext.AddOrUpdateAsync(r => userDbContext.UserGroups, _mapper.Map<UserGroupRef, UserGroup>(userGroupRef));
|
||||
await userDbContext.AddOrUpdateAsync(r => userDbContext.UserGroups, _mapper.Map<UserGroupRef, UserGroup>(userGroupRef));
|
||||
}
|
||||
|
||||
await userDbContext.SaveChangesAsync();
|
||||
@ -548,42 +552,45 @@ public class EFUserService : IUserService
|
||||
public void SetUserPhoto(int tenant, Guid id, byte[] photo)
|
||||
{
|
||||
using var userDbContext = _dbContextFactory.CreateDbContext();
|
||||
var strategy = userDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
strategy.Execute(async () =>
|
||||
var userPhoto = userDbContext.Photos.FirstOrDefault(r => r.UserId == id && r.Tenant == tenant);
|
||||
|
||||
if (photo != null && photo.Length != 0)
|
||||
{
|
||||
using var userDbContext = _dbContextFactory.CreateDbContext();
|
||||
using var tr = await userDbContext.Database.BeginTransactionAsync();
|
||||
|
||||
var userPhoto = await userDbContext.Photos.FirstOrDefaultAsync(r => r.UserId == id && r.Tenant == tenant);
|
||||
|
||||
if (photo != null && photo.Length != 0)
|
||||
if (userPhoto == null)
|
||||
{
|
||||
if (userPhoto == null)
|
||||
userPhoto = new UserPhoto
|
||||
{
|
||||
userPhoto = new UserPhoto
|
||||
{
|
||||
Tenant = tenant,
|
||||
UserId = id,
|
||||
Photo = photo
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
userPhoto.Photo = photo;
|
||||
}
|
||||
|
||||
await userDbContext.AddOrUpdateAsync(r => userDbContext.Photos, userPhoto);
|
||||
Tenant = tenant,
|
||||
UserId = id,
|
||||
Photo = photo
|
||||
};
|
||||
}
|
||||
else if (userPhoto != null)
|
||||
else
|
||||
{
|
||||
userDbContext.Photos.Remove(userPhoto);
|
||||
userPhoto.Photo = photo;
|
||||
}
|
||||
|
||||
await userDbContext.SaveChangesAsync();
|
||||
await tr.CommitAsync();
|
||||
}).GetAwaiter()
|
||||
.GetResult();
|
||||
|
||||
userDbContext.AddOrUpdate(userDbContext.Photos, userPhoto);
|
||||
|
||||
var userEntity = new User
|
||||
{
|
||||
Id = id,
|
||||
LastModified = DateTime.UtcNow,
|
||||
Tenant = tenant
|
||||
};
|
||||
|
||||
userDbContext.Users.Attach(userEntity);
|
||||
userDbContext.Entry(userEntity).Property(x => x.LastModified).IsModified = true;
|
||||
|
||||
}
|
||||
else if (userPhoto != null)
|
||||
{
|
||||
userDbContext.Photos.Remove(userPhoto);
|
||||
}
|
||||
|
||||
userDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
private IQueryable<User> GetUserQuery(UserDbContext userDbContext, int tenant)
|
||||
|
@ -39,7 +39,7 @@ public static class FilesConvertsExtension
|
||||
modelBuilder
|
||||
.Add(MySqlAddFilesConverts, Provider.MySql)
|
||||
.Add(PgSqlAddFilesConverts, Provider.PostgreSql)
|
||||
.HasData(
|
||||
.HasData(
|
||||
new FilesConverts { Input = ".csv", Output = ".ods" },
|
||||
new FilesConverts { Input = ".csv", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".csv", Output = ".ots" },
|
||||
@ -47,6 +47,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".csv", Output = ".xlsm" },
|
||||
new FilesConverts { Input = ".csv", Output = ".xltm" },
|
||||
new FilesConverts { Input = ".csv", Output = ".xltx" },
|
||||
|
||||
new FilesConverts { Input = ".doc", Output = ".docx" },
|
||||
new FilesConverts { Input = ".doc", Output = ".docm" },
|
||||
new FilesConverts { Input = ".doc", Output = ".dotm" },
|
||||
@ -59,6 +60,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".doc", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".doc", Output = ".rtf" },
|
||||
new FilesConverts { Input = ".doc", Output = ".txt" },
|
||||
|
||||
new FilesConverts { Input = ".docm", Output = ".docx" },
|
||||
new FilesConverts { Input = ".docm", Output = ".dotm" },
|
||||
new FilesConverts { Input = ".docm", Output = ".html" },
|
||||
@ -70,6 +72,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".docm", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".docm", Output = ".rtf" },
|
||||
new FilesConverts { Input = ".docm", Output = ".txt" },
|
||||
|
||||
new FilesConverts { Input = ".doct", Output = ".docx" },
|
||||
new FilesConverts { Input = ".docx", Output = ".odt" },
|
||||
new FilesConverts { Input = ".docx", Output = ".pdf" },
|
||||
@ -82,9 +85,11 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".docx", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".docx", Output = ".ott" },
|
||||
new FilesConverts { Input = ".docx", Output = ".docm" },
|
||||
|
||||
new FilesConverts { Input = ".docx", Output = ".docxf" },
|
||||
|
||||
new FilesConverts { Input = ".docxf", Output = ".docm" },
|
||||
new FilesConverts { Input = ".docxf", Output = ".docx" },
|
||||
new FilesConverts { Input = ".docxf", Output = ".dotm" },
|
||||
new FilesConverts { Input = ".docxf", Output = ".odt" },
|
||||
new FilesConverts { Input = ".docxf", Output = ".oform" },
|
||||
new FilesConverts { Input = ".docxf", Output = ".pdf" },
|
||||
@ -108,6 +113,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".dot", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".dot", Output = ".html" },
|
||||
new FilesConverts { Input = ".dot", Output = ".ott" },
|
||||
|
||||
new FilesConverts { Input = ".dotm", Output = ".docx" },
|
||||
new FilesConverts { Input = ".dotm", Output = ".odt" },
|
||||
new FilesConverts { Input = ".dotm", Output = ".pdf" },
|
||||
@ -119,6 +125,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".dotm", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".dotm", Output = ".html" },
|
||||
new FilesConverts { Input = ".dotm", Output = ".ott" },
|
||||
|
||||
new FilesConverts { Input = ".dotx", Output = ".docx" },
|
||||
new FilesConverts { Input = ".dotx", Output = ".odt" },
|
||||
new FilesConverts { Input = ".dotx", Output = ".pdf" },
|
||||
@ -130,6 +137,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".dotx", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".dotx", Output = ".html" },
|
||||
new FilesConverts { Input = ".dotx", Output = ".ott" },
|
||||
|
||||
new FilesConverts { Input = ".epub", Output = ".docx" },
|
||||
new FilesConverts { Input = ".epub", Output = ".odt" },
|
||||
new FilesConverts { Input = ".epub", Output = ".pdf" },
|
||||
@ -141,6 +149,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".epub", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".epub", Output = ".html" },
|
||||
new FilesConverts { Input = ".epub", Output = ".ott" },
|
||||
|
||||
new FilesConverts { Input = ".fb2", Output = ".docx" },
|
||||
new FilesConverts { Input = ".fb2", Output = ".odt" },
|
||||
new FilesConverts { Input = ".fb2", Output = ".pdf" },
|
||||
@ -152,12 +161,15 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".fb2", Output = ".epub" },
|
||||
new FilesConverts { Input = ".fb2", Output = ".html" },
|
||||
new FilesConverts { Input = ".fb2", Output = ".ott" },
|
||||
|
||||
new FilesConverts { Input = ".fodp", Output = ".odp" },
|
||||
new FilesConverts { Input = ".fodp", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".fodp", Output = ".pptx" },
|
||||
new FilesConverts { Input = ".fodp", Output = ".otp" },
|
||||
new FilesConverts { Input = ".fodp", Output = ".potm" },
|
||||
new FilesConverts { Input = ".fodp", Output = ".potx" },
|
||||
new FilesConverts { Input = ".fodp", Output = ".ppsm" },
|
||||
new FilesConverts { Input = ".fodp", Output = ".ppsx" },
|
||||
new FilesConverts { Input = ".fodp", Output = ".pptm" },
|
||||
new FilesConverts { Input = ".fods", Output = ".csv" },
|
||||
new FilesConverts { Input = ".fods", Output = ".ods" },
|
||||
@ -179,6 +191,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".fodt", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".fodt", Output = ".html" },
|
||||
new FilesConverts { Input = ".fodt", Output = ".ott" },
|
||||
|
||||
new FilesConverts { Input = ".html", Output = ".docx" },
|
||||
new FilesConverts { Input = ".html", Output = ".odt" },
|
||||
new FilesConverts { Input = ".html", Output = ".pdf" },
|
||||
@ -190,6 +203,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".html", Output = ".epub" },
|
||||
new FilesConverts { Input = ".html", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".html", Output = ".ott" },
|
||||
|
||||
new FilesConverts { Input = ".mht", Output = ".docx" },
|
||||
new FilesConverts { Input = ".mht", Output = ".odt" },
|
||||
new FilesConverts { Input = ".mht", Output = ".pdf" },
|
||||
@ -201,18 +215,25 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".mht", Output = ".epub" },
|
||||
new FilesConverts { Input = ".mht", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".mht", Output = ".ott" },
|
||||
|
||||
new FilesConverts { Input = ".odp", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".odp", Output = ".pptx" },
|
||||
new FilesConverts { Input = ".odp", Output = ".otp" },
|
||||
new FilesConverts { Input = ".odp", Output = ".potm" },
|
||||
new FilesConverts { Input = ".odp", Output = ".potx" },
|
||||
new FilesConverts { Input = ".odp", Output = ".ppsm" },
|
||||
new FilesConverts { Input = ".odp", Output = ".ppsx" },
|
||||
new FilesConverts { Input = ".odp", Output = ".pptm" },
|
||||
|
||||
new FilesConverts { Input = ".otp", Output = ".odp" },
|
||||
new FilesConverts { Input = ".otp", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".otp", Output = ".potm" },
|
||||
new FilesConverts { Input = ".otp", Output = ".potx" },
|
||||
new FilesConverts { Input = ".otp", Output = ".pptm" },
|
||||
new FilesConverts { Input = ".otp", Output = ".ppsm" },
|
||||
new FilesConverts { Input = ".otp", Output = ".ppsx" },
|
||||
new FilesConverts { Input = ".otp", Output = ".pptx" },
|
||||
|
||||
new FilesConverts { Input = ".ods", Output = ".csv" },
|
||||
new FilesConverts { Input = ".ods", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".ods", Output = ".xlsx" },
|
||||
@ -220,6 +241,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".ods", Output = ".xlsm" },
|
||||
new FilesConverts { Input = ".ods", Output = ".xltm" },
|
||||
new FilesConverts { Input = ".ods", Output = ".xltx" },
|
||||
|
||||
new FilesConverts { Input = ".ots", Output = ".csv" },
|
||||
new FilesConverts { Input = ".ots", Output = ".ods" },
|
||||
new FilesConverts { Input = ".ots", Output = ".pdf" },
|
||||
@ -227,7 +249,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".ots", Output = ".xltm" },
|
||||
new FilesConverts { Input = ".ots", Output = ".xltx" },
|
||||
new FilesConverts { Input = ".ots", Output = ".xlsx" },
|
||||
new FilesConverts { Input = ".oxps", Output = ".pdf" },
|
||||
|
||||
new FilesConverts { Input = ".odt", Output = ".docx" },
|
||||
new FilesConverts { Input = ".odt", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".odt", Output = ".rtf" },
|
||||
@ -239,6 +261,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".odt", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".odt", Output = ".html" },
|
||||
new FilesConverts { Input = ".odt", Output = ".ott" },
|
||||
|
||||
new FilesConverts { Input = ".ott", Output = ".docx" },
|
||||
new FilesConverts { Input = ".ott", Output = ".odt" },
|
||||
new FilesConverts { Input = ".ott", Output = ".pdf" },
|
||||
@ -250,6 +273,32 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".ott", Output = ".epub" },
|
||||
new FilesConverts { Input = ".ott", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".ott", Output = ".html" },
|
||||
|
||||
new FilesConverts { Input = ".oxps", Output = ".docm" },
|
||||
new FilesConverts { Input = ".oxps", Output = ".docx" },
|
||||
new FilesConverts { Input = ".oxps", Output = ".dotm" },
|
||||
new FilesConverts { Input = ".oxps", Output = ".dotx" },
|
||||
new FilesConverts { Input = ".oxps", Output = ".epub" },
|
||||
new FilesConverts { Input = ".oxps", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".oxps", Output = ".html" },
|
||||
new FilesConverts { Input = ".oxps", Output = ".odt" },
|
||||
new FilesConverts { Input = ".oxps", Output = ".ott" },
|
||||
new FilesConverts { Input = ".oxps", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".oxps", Output = ".rtf" },
|
||||
new FilesConverts { Input = ".oxps", Output = ".txt" },
|
||||
|
||||
new FilesConverts { Input = ".pdf", Output = ".docm" },
|
||||
new FilesConverts { Input = ".pdf", Output = ".docx" },
|
||||
new FilesConverts { Input = ".pdf", Output = ".dotm" },
|
||||
new FilesConverts { Input = ".pdf", Output = ".dotx" },
|
||||
new FilesConverts { Input = ".pdf", Output = ".epub" },
|
||||
new FilesConverts { Input = ".pdf", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".pdf", Output = ".html" },
|
||||
new FilesConverts { Input = ".pdf", Output = ".odt" },
|
||||
new FilesConverts { Input = ".pdf", Output = ".ott" },
|
||||
new FilesConverts { Input = ".pdf", Output = ".rtf" },
|
||||
new FilesConverts { Input = ".pdf", Output = ".txt" },
|
||||
|
||||
new FilesConverts { Input = ".pot", Output = ".odp" },
|
||||
new FilesConverts { Input = ".pot", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".pot", Output = ".pptx" },
|
||||
@ -257,18 +306,28 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".pot", Output = ".potm" },
|
||||
new FilesConverts { Input = ".pot", Output = ".potx" },
|
||||
new FilesConverts { Input = ".pot", Output = ".pptm" },
|
||||
new FilesConverts { Input = ".pot", Output = ".ppsm" },
|
||||
new FilesConverts { Input = ".pot", Output = ".ppsx" },
|
||||
|
||||
|
||||
new FilesConverts { Input = ".potm", Output = ".odp" },
|
||||
new FilesConverts { Input = ".potm", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".potm", Output = ".pptx" },
|
||||
new FilesConverts { Input = ".potm", Output = ".otp" },
|
||||
new FilesConverts { Input = ".potm", Output = ".potx" },
|
||||
new FilesConverts { Input = ".potm", Output = ".pptm" },
|
||||
new FilesConverts { Input = ".potm", Output = ".ppsm" },
|
||||
new FilesConverts { Input = ".potm", Output = ".ppsx" },
|
||||
|
||||
new FilesConverts { Input = ".potx", Output = ".odp" },
|
||||
new FilesConverts { Input = ".potx", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".potx", Output = ".pptx" },
|
||||
new FilesConverts { Input = ".potx", Output = ".otp" },
|
||||
new FilesConverts { Input = ".potx", Output = ".potm" },
|
||||
new FilesConverts { Input = ".potx", Output = ".pptm" },
|
||||
new FilesConverts { Input = ".potx", Output = ".ppsm" },
|
||||
new FilesConverts { Input = ".potx", Output = ".ppsx" },
|
||||
|
||||
new FilesConverts { Input = ".pps", Output = ".odp" },
|
||||
new FilesConverts { Input = ".pps", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".pps", Output = ".pptx" },
|
||||
@ -276,6 +335,9 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".pps", Output = ".potm" },
|
||||
new FilesConverts { Input = ".pps", Output = ".potx" },
|
||||
new FilesConverts { Input = ".pps", Output = ".pptm" },
|
||||
new FilesConverts { Input = ".pps", Output = ".ppsm" },
|
||||
new FilesConverts { Input = ".pps", Output = ".ppsx" },
|
||||
|
||||
new FilesConverts { Input = ".ppsm", Output = ".odp" },
|
||||
new FilesConverts { Input = ".ppsm", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".ppsm", Output = ".pptx" },
|
||||
@ -283,13 +345,17 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".ppsm", Output = ".potm" },
|
||||
new FilesConverts { Input = ".ppsm", Output = ".potx" },
|
||||
new FilesConverts { Input = ".ppsm", Output = ".pptm" },
|
||||
new FilesConverts { Input = ".ppsm", Output = ".ppsx" },
|
||||
|
||||
new FilesConverts { Input = ".ppsx", Output = ".odp" },
|
||||
new FilesConverts { Input = ".ppsx", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".ppsx", Output = ".pptx" },
|
||||
new FilesConverts { Input = ".ppsx", Output = ".otp" },
|
||||
new FilesConverts { Input = ".ppsx", Output = ".potm" },
|
||||
new FilesConverts { Input = ".ppsx", Output = ".potx" },
|
||||
new FilesConverts { Input = ".ppsx", Output = ".ppsm" },
|
||||
new FilesConverts { Input = ".ppsx", Output = ".pptm" },
|
||||
|
||||
new FilesConverts { Input = ".ppt", Output = ".odp" },
|
||||
new FilesConverts { Input = ".ppt", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".ppt", Output = ".pptx" },
|
||||
@ -297,12 +363,18 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".ppt", Output = ".potm" },
|
||||
new FilesConverts { Input = ".ppt", Output = ".potx" },
|
||||
new FilesConverts { Input = ".ppt", Output = ".pptm" },
|
||||
new FilesConverts { Input = ".ppt", Output = ".ppsm" },
|
||||
new FilesConverts { Input = ".ppt", Output = ".ppsx" },
|
||||
|
||||
new FilesConverts { Input = ".pptm", Output = ".odp" },
|
||||
new FilesConverts { Input = ".pptm", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".pptm", Output = ".pptx" },
|
||||
new FilesConverts { Input = ".pptm", Output = ".otp" },
|
||||
new FilesConverts { Input = ".pptm", Output = ".potm" },
|
||||
new FilesConverts { Input = ".pptm", Output = ".potx" },
|
||||
new FilesConverts { Input = ".pptm", Output = ".ppsm" },
|
||||
new FilesConverts { Input = ".pptm", Output = ".ppsx" },
|
||||
|
||||
new FilesConverts { Input = ".pptt", Output = ".pptx" },
|
||||
new FilesConverts { Input = ".pptx", Output = ".odp" },
|
||||
new FilesConverts { Input = ".pptx", Output = ".pdf" },
|
||||
@ -310,6 +382,9 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".pptx", Output = ".potm" },
|
||||
new FilesConverts { Input = ".pptx", Output = ".potx" },
|
||||
new FilesConverts { Input = ".pptx", Output = ".pptm" },
|
||||
new FilesConverts { Input = ".pptx", Output = ".ppsm" },
|
||||
new FilesConverts { Input = ".pptx", Output = ".ppsx" },
|
||||
|
||||
new FilesConverts { Input = ".rtf", Output = ".odt" },
|
||||
new FilesConverts { Input = ".rtf", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".rtf", Output = ".docx" },
|
||||
@ -321,6 +396,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".rtf", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".rtf", Output = ".html" },
|
||||
new FilesConverts { Input = ".rtf", Output = ".ott" },
|
||||
|
||||
new FilesConverts { Input = ".txt", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".txt", Output = ".docx" },
|
||||
new FilesConverts { Input = ".txt", Output = ".odt" },
|
||||
@ -332,6 +408,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".txt", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".txt", Output = ".html" },
|
||||
new FilesConverts { Input = ".txt", Output = ".ott" },
|
||||
|
||||
new FilesConverts { Input = ".xls", Output = ".csv" },
|
||||
new FilesConverts { Input = ".xls", Output = ".ods" },
|
||||
new FilesConverts { Input = ".xls", Output = ".pdf" },
|
||||
@ -340,6 +417,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".xls", Output = ".xlsm" },
|
||||
new FilesConverts { Input = ".xls", Output = ".xltm" },
|
||||
new FilesConverts { Input = ".xls", Output = ".xltx" },
|
||||
|
||||
new FilesConverts { Input = ".xlsm", Output = ".csv" },
|
||||
new FilesConverts { Input = ".xlsm", Output = ".xltm" },
|
||||
new FilesConverts { Input = ".xlsm", Output = ".xltx" },
|
||||
@ -347,6 +425,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".xlsm", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".xlsm", Output = ".ods" },
|
||||
new FilesConverts { Input = ".xlsm", Output = ".xlsx" },
|
||||
|
||||
new FilesConverts { Input = ".xlsx", Output = ".csv" },
|
||||
new FilesConverts { Input = ".xlsx", Output = ".ods" },
|
||||
new FilesConverts { Input = ".xlsx", Output = ".ots" },
|
||||
@ -355,6 +434,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".xlsx", Output = ".xltm" },
|
||||
new FilesConverts { Input = ".xlsx", Output = ".xltx" },
|
||||
new FilesConverts { Input = ".xlst", Output = ".xlsx" },
|
||||
|
||||
new FilesConverts { Input = ".xlt", Output = ".csv" },
|
||||
new FilesConverts { Input = ".xlt", Output = ".ods" },
|
||||
new FilesConverts { Input = ".xlt", Output = ".pdf" },
|
||||
@ -363,6 +443,7 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".xlt", Output = ".xlsm" },
|
||||
new FilesConverts { Input = ".xlt", Output = ".xltm" },
|
||||
new FilesConverts { Input = ".xlt", Output = ".xltx" },
|
||||
|
||||
new FilesConverts { Input = ".xltm", Output = ".csv" },
|
||||
new FilesConverts { Input = ".xltm", Output = ".ods" },
|
||||
new FilesConverts { Input = ".xltm", Output = ".pdf" },
|
||||
@ -377,7 +458,6 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".xltx", Output = ".xlsm" },
|
||||
new FilesConverts { Input = ".xltx", Output = ".xltm" },
|
||||
new FilesConverts { Input = ".xltx", Output = ".xlsx" },
|
||||
new FilesConverts { Input = ".xps", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".xml", Output = ".docm" },
|
||||
new FilesConverts { Input = ".xml", Output = ".docx" },
|
||||
new FilesConverts { Input = ".xml", Output = ".dotm" },
|
||||
@ -389,7 +469,20 @@ public static class FilesConvertsExtension
|
||||
new FilesConverts { Input = ".xml", Output = ".ott" },
|
||||
new FilesConverts { Input = ".xml", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".xml", Output = ".rtf" },
|
||||
new FilesConverts { Input = ".xml", Output = ".txt" }
|
||||
new FilesConverts { Input = ".xml", Output = ".txt" },
|
||||
|
||||
new FilesConverts { Input = ".xps", Output = ".docm" },
|
||||
new FilesConverts { Input = ".xps", Output = ".docx" },
|
||||
new FilesConverts { Input = ".xps", Output = ".dotm" },
|
||||
new FilesConverts { Input = ".xps", Output = ".dotx" },
|
||||
new FilesConverts { Input = ".xps", Output = ".epub" },
|
||||
new FilesConverts { Input = ".xps", Output = ".fb2" },
|
||||
new FilesConverts { Input = ".xps", Output = ".html" },
|
||||
new FilesConverts { Input = ".xps", Output = ".odt" },
|
||||
new FilesConverts { Input = ".xps", Output = ".ott" },
|
||||
new FilesConverts { Input = ".xps", Output = ".pdf" },
|
||||
new FilesConverts { Input = ".xps", Output = ".rtf" },
|
||||
new FilesConverts { Input = ".xps", Output = ".txt" }
|
||||
);
|
||||
|
||||
return modelBuilder;
|
||||
|
@ -59,7 +59,7 @@ public static class DbQuotaExtension
|
||||
Tenant = -1,
|
||||
Name = "trial",
|
||||
Description = null,
|
||||
Features = "trial,audit,ldap,sso,whitelabel,thirdparty,restore,total_size:107374182400,file_size:100,manager:1",
|
||||
Features = "trial,audit,ldap,sso,whitelabel,thirdparty,restore,oauth,total_size:107374182400,file_size:100,manager:1",
|
||||
Price = 0,
|
||||
ProductId = null,
|
||||
Visible = false
|
||||
@ -69,7 +69,7 @@ public static class DbQuotaExtension
|
||||
Tenant = -2,
|
||||
Name = "admin",
|
||||
Description = null,
|
||||
Features = "audit,ldap,sso,whitelabel,thirdparty,restore,contentsearch,total_size:107374182400,file_size:1024,manager:1",
|
||||
Features = "audit,ldap,sso,whitelabel,thirdparty,restore,oauth,contentsearch,total_size:107374182400,file_size:1024,manager:1",
|
||||
Price = 30,
|
||||
ProductId = "1002",
|
||||
Visible = true
|
||||
@ -79,7 +79,7 @@ public static class DbQuotaExtension
|
||||
Tenant = -3,
|
||||
Name = "startup",
|
||||
Description = null,
|
||||
Features = "free,total_size:2147483648,manager:5,room:5",
|
||||
Features = "free,total_size:2147483648,manager:3,room:12",
|
||||
Price = 0,
|
||||
ProductId = null,
|
||||
Visible = false
|
||||
|
@ -29,16 +29,16 @@ namespace ASC.Geolocation;
|
||||
[Scope]
|
||||
public class GeolocationHelper
|
||||
{
|
||||
private readonly IDbContextFactory<CustomDbContext> _dbContextFactory;
|
||||
private readonly CreatorDbContext _creatorDbContext;
|
||||
private readonly ILogger<GeolocationHelper> _logger;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public GeolocationHelper(
|
||||
IDbContextFactory<CustomDbContext> dbContextFactory,
|
||||
CreatorDbContext creatorDbContext,
|
||||
ILogger<GeolocationHelper> logger,
|
||||
IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_dbContextFactory = dbContextFactory;
|
||||
_creatorDbContext = creatorDbContext;
|
||||
_logger = logger;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
@ -47,7 +47,7 @@ public class GeolocationHelper
|
||||
{
|
||||
try
|
||||
{
|
||||
using var dbContext = _dbContextFactory.CreateDbContext();
|
||||
using var dbContext = _creatorDbContext.CreateDbContext<CustomDbContext>(nameConnectionString: "teamlabsite");
|
||||
var ipformatted = FormatIP(ip);
|
||||
var q = dbContext.DbipLocation
|
||||
.Where(r => r.IPStart.CompareTo(ipformatted) <= 0)
|
||||
|
@ -100,6 +100,25 @@ public class NotifyEngine : INotifyEngine, IDisposable
|
||||
_methodsEvent.Set();
|
||||
}
|
||||
|
||||
internal void RegisterSendMethod(Func<DateTime, Task> method, string cron)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(method);
|
||||
ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(cron);
|
||||
|
||||
var w = new SendMethodWrapper(method, cron, _logger);
|
||||
lock (_sendMethods)
|
||||
{
|
||||
if (!_notifyScheduler.IsAlive)
|
||||
{
|
||||
_notifyScheduler.Start();
|
||||
}
|
||||
|
||||
_sendMethods.Remove(w);
|
||||
_sendMethods.Add(w);
|
||||
}
|
||||
_methodsEvent.Set();
|
||||
}
|
||||
|
||||
internal void UnregisterSendMethod(Action<DateTime> method)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(method);
|
||||
@ -124,7 +143,7 @@ public class NotifyEngine : INotifyEngine, IDisposable
|
||||
copy = _sendMethods.ToList();
|
||||
}
|
||||
|
||||
foreach(var w in copy)
|
||||
foreach (var w in copy)
|
||||
{
|
||||
if (!w.ScheduleDate.HasValue)
|
||||
{
|
||||
@ -590,6 +609,7 @@ public class NotifyEngine : INotifyEngine, IDisposable
|
||||
private readonly SemaphoreSlim _semaphore;
|
||||
private readonly CronExpression _cronExpression;
|
||||
private readonly Action<DateTime> _method;
|
||||
private readonly Func<DateTime, Task> _asyncMethod;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public DateTime? ScheduleDate { get; private set; }
|
||||
@ -608,6 +628,11 @@ public class NotifyEngine : INotifyEngine, IDisposable
|
||||
UpdateScheduleDate(DateTime.UtcNow);
|
||||
}
|
||||
|
||||
public SendMethodWrapper(Func<DateTime, Task> method, string cron, ILogger log) : this((Action<DateTime>)null, cron, log)
|
||||
{
|
||||
_asyncMethod = method;
|
||||
}
|
||||
|
||||
public void UpdateScheduleDate(DateTime d)
|
||||
{
|
||||
try
|
||||
@ -626,11 +651,18 @@ public class NotifyEngine : INotifyEngine, IDisposable
|
||||
public async Task InvokeSendMethod(DateTime d)
|
||||
{
|
||||
await _semaphore.WaitAsync();
|
||||
await Task.Run(() =>
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_method(d);
|
||||
if (_method != null)
|
||||
{
|
||||
_method(d);
|
||||
}
|
||||
else if (_asyncMethod != null)
|
||||
{
|
||||
await _asyncMethod(d);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -642,7 +674,7 @@ public class NotifyEngine : INotifyEngine, IDisposable
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is SendMethodWrapper w && _method.Equals(w._method);
|
||||
return obj is SendMethodWrapper w && ((_method != null && _method.Equals(w._method)) || (_asyncMethod != null && _asyncMethod.Equals(w._asyncMethod)));
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
|
34
common/ASC.Core.Common/Quota/Features/FreeFeature.cs
Normal file
34
common/ASC.Core.Common/Quota/Features/FreeFeature.cs
Normal file
@ -0,0 +1,34 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// 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
|
||||
|
||||
namespace ASC.Core.Common.Quota.Features;
|
||||
public class FreeFeature : TenantQuotaFeatureFlag
|
||||
{
|
||||
public override string Name { get => "free"; }
|
||||
public FreeFeature(TenantQuota tenantQuota) : base(tenantQuota)
|
||||
{
|
||||
}
|
||||
}
|
64
common/ASC.Core.Common/Quota/QuotaSocketManager.cs
Normal file
64
common/ASC.Core.Common/Quota/QuotaSocketManager.cs
Normal file
@ -0,0 +1,64 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// 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
|
||||
|
||||
namespace ASC.Core.Common.Quota;
|
||||
public class QuotaSocketManager : SocketServiceClient
|
||||
{
|
||||
private readonly TenantManager _tenantManager;
|
||||
|
||||
public override string Hub => "files";
|
||||
|
||||
public QuotaSocketManager(
|
||||
ILogger<SocketServiceClient> logger,
|
||||
IHttpClientFactory clientFactory,
|
||||
MachinePseudoKeys mashinePseudoKeys,
|
||||
TenantManager tenantManager,
|
||||
IConfiguration configuration) : base(logger, clientFactory, mashinePseudoKeys, configuration)
|
||||
{
|
||||
_tenantManager = tenantManager;
|
||||
}
|
||||
|
||||
public async Task ChangeQuotaUsedValue(string featureId, object value)
|
||||
{
|
||||
var room = GetQuotaRoom();
|
||||
|
||||
await MakeRequest("change-quota-used-value", new { room, featureId, value });
|
||||
}
|
||||
|
||||
public async Task ChangeQuotaFeatureValue(string featureId, object value)
|
||||
{
|
||||
var room = GetQuotaRoom();
|
||||
|
||||
await MakeRequest("change-quota-feature-value", new { room, featureId, value });
|
||||
}
|
||||
|
||||
private string GetQuotaRoom()
|
||||
{
|
||||
var tenantId = _tenantManager.GetCurrentTenant().Id;
|
||||
|
||||
return $"{tenantId}-quota";
|
||||
}
|
||||
}
|
@ -67,7 +67,7 @@ public class TenantQuotaFeature<T> : TenantQuotaFeature
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual T Default { get; }
|
||||
public virtual T Default { get; }
|
||||
|
||||
public TenantQuotaFeature(TenantQuota tenantQuota)
|
||||
{
|
||||
@ -83,7 +83,7 @@ public class TenantQuotaFeature<T> : TenantQuotaFeature
|
||||
|
||||
public class TenantQuotaFeatureCount : TenantQuotaFeature<int>
|
||||
{
|
||||
protected override int Default => int.MaxValue;
|
||||
public override int Default => int.MaxValue;
|
||||
|
||||
public TenantQuotaFeatureCount(TenantQuota tenantQuota) : base(tenantQuota)
|
||||
{
|
||||
@ -105,7 +105,7 @@ public class TenantQuotaFeatureCount : TenantQuotaFeature<int>
|
||||
|
||||
public class TenantQuotaFeatureSize : TenantQuotaFeature<long>
|
||||
{
|
||||
protected override long Default => long.MaxValue;
|
||||
public override long Default => long.MaxValue;
|
||||
|
||||
public TenantQuotaFeatureSize(TenantQuota tenantQuota) : base(tenantQuota)
|
||||
{
|
||||
|
50
common/ASC.Core.Common/Quota/TenantQuotaFeatureStatHelper.cs
Normal file
50
common/ASC.Core.Common/Quota/TenantQuotaFeatureStatHelper.cs
Normal file
@ -0,0 +1,50 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// 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
|
||||
|
||||
namespace ASC.Core.Common.Quota;
|
||||
[Scope]
|
||||
public class TenantQuotaFeatureStatHelper
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
public TenantQuotaFeatureStatHelper(IServiceProvider serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
public async Task<(string Name, T1 Value)> GetStat<T, T1>() where T : TenantQuotaFeature
|
||||
{
|
||||
var statisticProvider = (ITenantQuotaFeatureStat<T1>)_serviceProvider.GetService(typeof(ITenantQuotaFeatureStat<,>).MakeGenericType(typeof(T), typeof(T1)));
|
||||
|
||||
var quota = new TenantQuota();
|
||||
var name = quota.GetFeature<T>().Name;
|
||||
|
||||
if (statisticProvider != null)
|
||||
{
|
||||
return (name, await statisticProvider.GetValue());
|
||||
}
|
||||
|
||||
return (name, default(T1));
|
||||
}
|
||||
}
|
@ -222,13 +222,13 @@ public class TenantQuota : IMapFrom<DbQuota>
|
||||
|
||||
_countUserFeature = new CountUserFeature(this) { Order = 1 };
|
||||
_countPaidUserFeature = new CountPaidUserFeature(this);
|
||||
_usersInRoomFeature = new UsersInRoomFeature(this) { Order = 8 };
|
||||
_usersInRoomFeature = new UsersInRoomFeature(this) { Order = 8, Visible = false };
|
||||
_countRoomFeature = new CountRoomFeature(this) { Order = 2 };
|
||||
_maxTotalSizeFeature = new MaxTotalSizeFeature(this);
|
||||
_maxFileSizeFeature = new MaxFileSizeFeature(this);
|
||||
_nonProfitFeature = new TenantQuotaFeatureFlag(this) { Name = "non-profit", Visible = false };
|
||||
_trialFeature = new TenantQuotaFeatureFlag(this) { Name = "trial", Visible = false };
|
||||
_freeFeature = new TenantQuotaFeatureFlag(this) { Name = "free", Visible = false };
|
||||
_freeFeature = new FreeFeature(this) { Visible = false };
|
||||
_updateFeature = new TenantQuotaFeatureFlag(this) { Name = "update", Visible = false };
|
||||
_auditFeature = new TenantQuotaFeatureFlag(this) { Name = "audit", Order = 7 };
|
||||
_docsEditionFeature = new TenantQuotaFeatureFlag(this) { Name = "docs", Visible = false };
|
||||
@ -323,7 +323,7 @@ public class TenantQuota : IMapFrom<DbQuota>
|
||||
return quota;
|
||||
}
|
||||
|
||||
var newQuota = new TenantQuota(quota);
|
||||
var newQuota = new TenantQuota(old);
|
||||
newQuota.Price += quota.Price;
|
||||
newQuota.Visible &= quota.Visible;
|
||||
newQuota.ProductId = "";
|
||||
@ -336,11 +336,31 @@ public class TenantQuota : IMapFrom<DbQuota>
|
||||
}
|
||||
else if (f is TenantQuotaFeatureCount count)
|
||||
{
|
||||
count.Value += quota.GetFeature<int>(f.Name).Value;
|
||||
var currentValue = count.Value;
|
||||
var newValue = quota.GetFeature<int>(f.Name).Value;
|
||||
|
||||
if (currentValue == count.Default && newValue != currentValue)
|
||||
{
|
||||
count.Value = newValue;
|
||||
}
|
||||
else if (currentValue != count.Default && newValue != count.Default)
|
||||
{
|
||||
count.Value += newValue;
|
||||
}
|
||||
}
|
||||
else if (f is TenantQuotaFeatureSize length)
|
||||
{
|
||||
length.Value += quota.GetFeature<long>(f.Name).Value;
|
||||
var currentValue = length.Value;
|
||||
var newValue = quota.GetFeature<long>(f.Name).Value;
|
||||
|
||||
if (currentValue == length.Default && newValue != currentValue)
|
||||
{
|
||||
length.Value = newValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
length.Value += newValue;
|
||||
}
|
||||
}
|
||||
else if (f is TenantQuotaFeatureFlag flag)
|
||||
{
|
||||
|
@ -60,7 +60,7 @@ public class BackupRepository : IBackupRepository
|
||||
public List<BackupRecord> GetExpiredBackupRecords()
|
||||
{
|
||||
using var backupContext = _dbContextFactory.CreateDbContext();
|
||||
return backupContext.Backups.AsNoTracking().Where(b => b.ExpiresOn != DateTime.MinValue && b.ExpiresOn <= DateTime.UtcNow).ToList();
|
||||
return backupContext.Backups.AsNoTracking().Where(b => b.ExpiresOn != DateTime.MinValue && b.ExpiresOn <= DateTime.UtcNow && b.Removed == false).ToList();
|
||||
}
|
||||
|
||||
public List<BackupRecord> GetScheduledBackupRecords()
|
||||
|
@ -709,14 +709,18 @@ public class BackupPortalTask : PortalTaskBase
|
||||
foreach (var file in group)
|
||||
{
|
||||
var storage = StorageFactory.GetStorage(TenantId, group.Key);
|
||||
var file1 = file;
|
||||
var file1 = file;
|
||||
Stream fileStream = null;
|
||||
await ActionInvoker.Try(async state =>
|
||||
{
|
||||
var f = (BackupFileInfo)state;
|
||||
using var fileStream = await storage.GetReadStreamAsync(f.Domain, f.Path);
|
||||
await writer.WriteEntryAsync(file1.GetZipKey(), fileStream);
|
||||
fileStream = await storage.GetReadStreamAsync(f.Domain, f.Path);
|
||||
}, file, 5, error => _logger.WarningCanNotBackupFile(file1.Module, file1.Path, error));
|
||||
|
||||
if(fileStream != null)
|
||||
{
|
||||
await writer.WriteEntryAsync(file1.GetZipKey(), fileStream);
|
||||
fileStream.Dispose();
|
||||
}
|
||||
SetCurrentStepProgress((int)(++filesProcessed * 100 / (double)filesCount));
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,9 @@ public abstract class BaseStorage : IDataStore
|
||||
protected readonly ILoggerProvider _options;
|
||||
protected readonly IHttpClientFactory _clientFactory;
|
||||
|
||||
private readonly TenantQuotaFeatureStatHelper _tenantQuotaFeatureStatHelper;
|
||||
private readonly QuotaSocketManager _quotaSocketManager;
|
||||
|
||||
public BaseStorage(
|
||||
TempStream tempStream,
|
||||
TenantManager tenantManager,
|
||||
@ -56,7 +59,9 @@ public abstract class BaseStorage : IDataStore
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
ILoggerProvider options,
|
||||
ILogger logger,
|
||||
IHttpClientFactory clientFactory)
|
||||
IHttpClientFactory clientFactory,
|
||||
TenantQuotaFeatureStatHelper tenantQuotaFeatureStatHelper,
|
||||
QuotaSocketManager quotaSocketManager)
|
||||
{
|
||||
|
||||
_tempStream = tempStream;
|
||||
@ -67,6 +72,8 @@ public abstract class BaseStorage : IDataStore
|
||||
_clientFactory = clientFactory;
|
||||
Logger = logger;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_tenantQuotaFeatureStatHelper = tenantQuotaFeatureStatHelper;
|
||||
_quotaSocketManager = quotaSocketManager;
|
||||
}
|
||||
|
||||
public TimeSpan GetExpire(string domain)
|
||||
@ -334,19 +341,23 @@ public abstract class BaseStorage : IDataStore
|
||||
public abstract string GetPostParams(string domain, string directoryPath, long maxUploadSize, string contentType,
|
||||
string contentDisposition);
|
||||
|
||||
internal void QuotaUsedAdd(string domain, long size, bool quotaCheckFileSize = true)
|
||||
internal async Task QuotaUsedAdd(string domain, long size, bool quotaCheckFileSize = true)
|
||||
{
|
||||
if (QuotaController != null)
|
||||
{
|
||||
QuotaController.QuotaUsedAdd(Modulename, domain, DataList.GetData(domain), size, quotaCheckFileSize);
|
||||
var(name, value) = await _tenantQuotaFeatureStatHelper.GetStat<MaxTotalSizeFeature, long>();
|
||||
_ = _quotaSocketManager.ChangeQuotaUsedValue(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
internal void QuotaUsedDelete(string domain, long size)
|
||||
internal async Task QuotaUsedDelete(string domain, long size)
|
||||
{
|
||||
if (QuotaController != null)
|
||||
{
|
||||
QuotaController.QuotaUsedDelete(Modulename, domain, DataList.GetData(domain), size);
|
||||
var (name, value) = await _tenantQuotaFeatureStatHelper.GetStat<MaxTotalSizeFeature, long>();
|
||||
_ = _quotaSocketManager.ChangeQuotaUsedValue(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,8 +75,10 @@ public class DiscDataStore : BaseStorage
|
||||
ILogger<DiscDataStore> logger,
|
||||
EncryptionSettingsHelper encryptionSettingsHelper,
|
||||
EncryptionFactory encryptionFactory,
|
||||
IHttpClientFactory clientFactory)
|
||||
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options, logger, clientFactory)
|
||||
IHttpClientFactory clientFactory,
|
||||
TenantQuotaFeatureStatHelper tenantQuotaFeatureStatHelper,
|
||||
QuotaSocketManager quotaSocketManager)
|
||||
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options, logger, clientFactory, tenantQuotaFeatureStatHelper, quotaSocketManager)
|
||||
{
|
||||
_encryptionSettingsHelper = encryptionSettingsHelper;
|
||||
_encryptionFactory = encryptionFactory;
|
||||
@ -143,18 +145,18 @@ public class DiscDataStore : BaseStorage
|
||||
{
|
||||
return SaveAsync(domain, path, stream);
|
||||
}
|
||||
private bool EnableQuotaCheck(string domain)
|
||||
{
|
||||
return (QuotaController != null) && !domain.EndsWith("_temp");
|
||||
}
|
||||
private bool EnableQuotaCheck(string domain)
|
||||
{
|
||||
return (QuotaController != null) && !domain.EndsWith("_temp");
|
||||
}
|
||||
|
||||
public override Task<Uri> SaveAsync(string domain, string path, Stream stream)
|
||||
{
|
||||
Logger.DebugSavePath(path);
|
||||
|
||||
var buffered = _tempStream.GetBuffered(stream);
|
||||
|
||||
if (EnableQuotaCheck(domain))
|
||||
|
||||
if (EnableQuotaCheck(domain))
|
||||
{
|
||||
QuotaController.QuotaUsedCheck(buffered.Length);
|
||||
}
|
||||
@ -193,7 +195,7 @@ public class DiscDataStore : BaseStorage
|
||||
fslen = fs.Length;
|
||||
}
|
||||
|
||||
QuotaUsedAdd(domain, fslen);
|
||||
await QuotaUsedAdd(domain, fslen);
|
||||
|
||||
_crypt.EncryptFile(target);
|
||||
|
||||
@ -226,7 +228,7 @@ public class DiscDataStore : BaseStorage
|
||||
return string.Format("{0}_{1}", chunkNumber, uploadId);
|
||||
}
|
||||
|
||||
public override Task<Uri> FinalizeChunkedUploadAsync(string domain, string path, string uploadId, Dictionary<int, string> eTags)
|
||||
public override async Task<Uri> FinalizeChunkedUploadAsync(string domain, string path, string uploadId, Dictionary<int, string> eTags)
|
||||
{
|
||||
var target = GetTarget(domain, path);
|
||||
|
||||
@ -238,12 +240,12 @@ public class DiscDataStore : BaseStorage
|
||||
}
|
||||
|
||||
var size = _crypt.GetFileSize(target);
|
||||
QuotaUsedAdd(domain, size);
|
||||
await QuotaUsedAdd(domain, size);
|
||||
}
|
||||
|
||||
_crypt.EncryptFile(target);
|
||||
|
||||
return GetUriAsync(domain, path);
|
||||
return await GetUriAsync(domain, path);
|
||||
}
|
||||
|
||||
public override Task AbortChunkedUploadAsync(string domain, string path, string uploadId)
|
||||
@ -258,7 +260,7 @@ public class DiscDataStore : BaseStorage
|
||||
|
||||
#endregion
|
||||
|
||||
public override Task DeleteAsync(string domain, string path)
|
||||
public override async Task DeleteAsync(string domain, string path)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
@ -269,8 +271,7 @@ public class DiscDataStore : BaseStorage
|
||||
var size = _crypt.GetFileSize(target);
|
||||
File.Delete(target);
|
||||
|
||||
QuotaUsedDelete(domain, size);
|
||||
return Task.CompletedTask; ;
|
||||
await QuotaUsedDelete(domain, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -278,7 +279,7 @@ public class DiscDataStore : BaseStorage
|
||||
}
|
||||
}
|
||||
|
||||
public override Task DeleteFilesAsync(string domain, List<string> paths)
|
||||
public override async Task DeleteFilesAsync(string domain, List<string> paths)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(paths);
|
||||
|
||||
@ -294,13 +295,11 @@ public class DiscDataStore : BaseStorage
|
||||
var size = _crypt.GetFileSize(target);
|
||||
File.Delete(target);
|
||||
|
||||
QuotaUsedDelete(domain, size);
|
||||
await QuotaUsedDelete(domain, size);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task DeleteFilesAsync(string domain, string folderPath, string pattern, bool recursive)
|
||||
public override async Task DeleteFilesAsync(string domain, string folderPath, string pattern, bool recursive)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(folderPath);
|
||||
|
||||
@ -313,9 +312,8 @@ public class DiscDataStore : BaseStorage
|
||||
{
|
||||
var size = _crypt.GetFileSize(entry);
|
||||
File.Delete(entry);
|
||||
QuotaUsedDelete(domain, size);
|
||||
await QuotaUsedDelete(domain, size);
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -323,7 +321,7 @@ public class DiscDataStore : BaseStorage
|
||||
}
|
||||
}
|
||||
|
||||
public override Task DeleteFilesAsync(string domain, string folderPath, DateTime fromDate, DateTime toDate)
|
||||
public override async Task DeleteFilesAsync(string domain, string folderPath, DateTime fromDate, DateTime toDate)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(folderPath);
|
||||
|
||||
@ -339,7 +337,7 @@ public class DiscDataStore : BaseStorage
|
||||
{
|
||||
var size = _crypt.GetFileSize(entry);
|
||||
File.Delete(entry);
|
||||
QuotaUsedDelete(domain, size);
|
||||
await QuotaUsedDelete(domain, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -347,8 +345,6 @@ public class DiscDataStore : BaseStorage
|
||||
{
|
||||
throw new DirectoryNotFoundException($"Directory '{targetDir}' not found");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task MoveDirectoryAsync(string srcdomain, string srcdir, string newdomain, string newdir)
|
||||
@ -367,7 +363,7 @@ public class DiscDataStore : BaseStorage
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task<Uri> MoveAsync(string srcdomain, string srcpath, string newdomain, string newpath, bool quotaCheckFileSize = true)
|
||||
public override async Task<Uri> MoveAsync(string srcdomain, string srcpath, string newdomain, string newpath, bool quotaCheckFileSize = true)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(srcpath);
|
||||
ArgumentNullException.ThrowIfNull(newpath);
|
||||
@ -392,14 +388,14 @@ public class DiscDataStore : BaseStorage
|
||||
|
||||
File.Move(target, newtarget);
|
||||
|
||||
QuotaUsedDelete(srcdomain, flength);
|
||||
QuotaUsedAdd(newdomain, flength, quotaCheckFileSize);
|
||||
await QuotaUsedDelete(srcdomain, flength);
|
||||
await QuotaUsedAdd(newdomain, flength, quotaCheckFileSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FileNotFoundException("File not found", Path.GetFullPath(target));
|
||||
}
|
||||
return GetUriAsync(newdomain, newpath);
|
||||
return await GetUriAsync(newdomain, newpath);
|
||||
}
|
||||
|
||||
public override Task<bool> IsDirectoryAsync(string domain, string path)
|
||||
@ -415,7 +411,7 @@ public class DiscDataStore : BaseStorage
|
||||
return Task.FromResult(!string.IsNullOrEmpty(targetDir) && Directory.Exists(targetDir));
|
||||
}
|
||||
|
||||
public override Task DeleteDirectoryAsync(string domain, string path)
|
||||
public override async Task DeleteDirectoryAsync(string domain, string path)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
@ -434,7 +430,7 @@ public class DiscDataStore : BaseStorage
|
||||
|
||||
if (!Directory.Exists(targetDir))
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
var entries = Directory.GetFiles(targetDir, "*.*", SearchOption.AllDirectories);
|
||||
@ -446,8 +442,7 @@ public class DiscDataStore : BaseStorage
|
||||
|
||||
Directory.Delete(targetDir, true);
|
||||
|
||||
QuotaUsedDelete(domain, size);
|
||||
return Task.CompletedTask;
|
||||
await QuotaUsedDelete(domain, size);
|
||||
}
|
||||
|
||||
public override Task<long> GetFileSizeAsync(string domain, string path)
|
||||
@ -488,7 +483,7 @@ public class DiscDataStore : BaseStorage
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
public override Task DeleteExpiredAsync(string domain, string folderPath, TimeSpan oldThreshold)
|
||||
public override async Task DeleteExpiredAsync(string domain, string folderPath, TimeSpan oldThreshold)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(folderPath);
|
||||
|
||||
@ -496,7 +491,7 @@ public class DiscDataStore : BaseStorage
|
||||
var targetDir = GetTarget(domain, folderPath);
|
||||
if (!Directory.Exists(targetDir))
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
var entries = Directory.GetFiles(targetDir, "*.*", SearchOption.TopDirectoryOnly);
|
||||
@ -508,11 +503,9 @@ public class DiscDataStore : BaseStorage
|
||||
var size = _crypt.GetFileSize(entry);
|
||||
File.Delete(entry);
|
||||
|
||||
QuotaUsedDelete(domain, size);
|
||||
await QuotaUsedDelete(domain, size);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override string GetUploadForm(string domain, string directoryPath, string redirectTo, long maxUploadSize, string contentType, string contentDisposition, string submitLabel)
|
||||
@ -608,7 +601,7 @@ public class DiscDataStore : BaseStorage
|
||||
return Task.FromResult(size);
|
||||
}
|
||||
|
||||
public override Task<Uri> CopyAsync(string srcdomain, string srcpath, string newdomain, string newpath)
|
||||
public override async Task<Uri> CopyAsync(string srcdomain, string srcpath, string newdomain, string newpath)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(srcpath);
|
||||
ArgumentNullException.ThrowIfNull(newpath);
|
||||
@ -626,16 +619,16 @@ public class DiscDataStore : BaseStorage
|
||||
File.Copy(target, newtarget, true);
|
||||
|
||||
var flength = _crypt.GetFileSize(target);
|
||||
QuotaUsedAdd(newdomain, flength);
|
||||
await QuotaUsedAdd(newdomain, flength);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FileNotFoundException("File not found", Path.GetFullPath(target));
|
||||
}
|
||||
return GetUriAsync(newdomain, newpath);
|
||||
return await GetUriAsync(newdomain, newpath);
|
||||
}
|
||||
|
||||
public override Task CopyDirectoryAsync(string srcdomain, string srcdir, string newdomain, string newdir)
|
||||
public override async Task CopyDirectoryAsync(string srcdomain, string srcdir, string newdomain, string newdir)
|
||||
{
|
||||
var target = GetTarget(srcdomain, srcdir);
|
||||
var newtarget = GetTarget(newdomain, newdir);
|
||||
@ -643,8 +636,7 @@ public class DiscDataStore : BaseStorage
|
||||
var diSource = new DirectoryInfo(target);
|
||||
var diTarget = new DirectoryInfo(newtarget);
|
||||
|
||||
CopyAll(diSource, diTarget, newdomain);
|
||||
return Task.CompletedTask;
|
||||
await CopyAll(diSource, diTarget, newdomain);
|
||||
}
|
||||
|
||||
|
||||
@ -684,7 +676,7 @@ public class DiscDataStore : BaseStorage
|
||||
return SaveAsync(domain, path, stream);
|
||||
}
|
||||
|
||||
private void CopyAll(DirectoryInfo source, DirectoryInfo target, string newdomain)
|
||||
private async Task CopyAll(DirectoryInfo source, DirectoryInfo target, string newdomain)
|
||||
{
|
||||
// Check if the target directory exists, if not, create it.
|
||||
if (!Directory.Exists(target.FullName))
|
||||
@ -698,14 +690,14 @@ public class DiscDataStore : BaseStorage
|
||||
var fp = CrossPlatform.PathCombine(target.ToString(), fi.Name);
|
||||
fi.CopyTo(fp, true);
|
||||
var size = _crypt.GetFileSize(fp);
|
||||
QuotaUsedAdd(newdomain, size);
|
||||
await QuotaUsedAdd(newdomain, size);
|
||||
}
|
||||
|
||||
// Copy each subdirectory using recursion.
|
||||
foreach (var diSourceSubDir in source.GetDirectories())
|
||||
{
|
||||
var nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
|
||||
CopyAll(diSourceSubDir, nextTargetSubDir, newdomain);
|
||||
await CopyAll(diSourceSubDir, nextTargetSubDir, newdomain);
|
||||
}
|
||||
}
|
||||
|
||||
@ -768,7 +760,7 @@ public class DiscDataStore : BaseStorage
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
var target = GetTarget(domain, path);
|
||||
var target = GetTarget(domain, path);
|
||||
var lastModificationDate = File.Exists(target) ? File.GetLastWriteTimeUtc(target) : throw new FileNotFoundException("File not found" + target);
|
||||
var etag = '"' + lastModificationDate.Ticks.ToString("X8", CultureInfo.InvariantCulture) + '"';
|
||||
|
||||
|
@ -48,8 +48,10 @@ public class GoogleCloudStorage : BaseStorage
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
ILoggerProvider factory,
|
||||
ILogger<GoogleCloudStorage> options,
|
||||
IHttpClientFactory clientFactory)
|
||||
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, factory, options, clientFactory)
|
||||
IHttpClientFactory clientFactory,
|
||||
TenantQuotaFeatureStatHelper tenantQuotaFeatureStatHelper,
|
||||
QuotaSocketManager quotaSocketManager)
|
||||
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, factory, options, clientFactory, tenantQuotaFeatureStatHelper, quotaSocketManager)
|
||||
{
|
||||
}
|
||||
|
||||
@ -234,7 +236,7 @@ public class GoogleCloudStorage : BaseStorage
|
||||
|
||||
// InvalidateCloudFront(MakePath(domain, path));
|
||||
|
||||
QuotaUsedAdd(domain, buffered.Length);
|
||||
await QuotaUsedAdd(domain, buffered.Length);
|
||||
|
||||
return await GetUriAsync(domain, path);
|
||||
}
|
||||
@ -248,7 +250,7 @@ public class GoogleCloudStorage : BaseStorage
|
||||
|
||||
await storage.DeleteObjectAsync(_bucket, key);
|
||||
|
||||
QuotaUsedDelete(domain, size);
|
||||
await QuotaUsedDelete(domain, size);
|
||||
}
|
||||
|
||||
public override async Task DeleteFilesAsync(string domain, string folderPath, string pattern, bool recursive)
|
||||
@ -271,7 +273,7 @@ public class GoogleCloudStorage : BaseStorage
|
||||
await foreach (var obj in objToDel)
|
||||
{
|
||||
await storage.DeleteObjectAsync(_bucket, obj.Name);
|
||||
QuotaUsedDelete(domain, Convert.ToInt64(obj.Size));
|
||||
await QuotaUsedDelete(domain, Convert.ToInt64(obj.Size));
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,7 +327,7 @@ public class GoogleCloudStorage : BaseStorage
|
||||
|
||||
if (quotaUsed > 0)
|
||||
{
|
||||
QuotaUsedDelete(domain, quotaUsed);
|
||||
await QuotaUsedDelete(domain, quotaUsed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,7 +341,7 @@ public class GoogleCloudStorage : BaseStorage
|
||||
await foreach (var obj in objToDel)
|
||||
{
|
||||
await storage.DeleteObjectAsync(_bucket, obj.Name);
|
||||
QuotaUsedDelete(domain, Convert.ToInt64(obj.Size));
|
||||
await QuotaUsedDelete(domain, Convert.ToInt64(obj.Size));
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,8 +380,8 @@ public class GoogleCloudStorage : BaseStorage
|
||||
|
||||
await DeleteAsync(srcdomain, srcpath);
|
||||
|
||||
QuotaUsedDelete(srcdomain, size);
|
||||
QuotaUsedAdd(newdomain, size, quotaCheckFileSize);
|
||||
await QuotaUsedDelete(srcdomain, size);
|
||||
await QuotaUsedAdd(newdomain, size, quotaCheckFileSize);
|
||||
|
||||
return await GetUriAsync(newdomain, newpath);
|
||||
}
|
||||
@ -455,7 +457,7 @@ public class GoogleCloudStorage : BaseStorage
|
||||
await foreach (var obj in objToDel)
|
||||
{
|
||||
await storage.DeleteObjectAsync(_bucket, obj.Name);
|
||||
QuotaUsedDelete(domain, Convert.ToInt64(obj.Size));
|
||||
await QuotaUsedDelete(domain, Convert.ToInt64(obj.Size));
|
||||
}
|
||||
}
|
||||
|
||||
@ -549,7 +551,7 @@ public class GoogleCloudStorage : BaseStorage
|
||||
|
||||
await storage.CopyObjectAsync(_bucket, MakePath(srcdomain, srcpath), _bucket, MakePath(newdomain, newpath), options);
|
||||
|
||||
QuotaUsedAdd(newdomain, size);
|
||||
await QuotaUsedAdd(newdomain, size);
|
||||
|
||||
return await GetUriAsync(newdomain, newpath);
|
||||
}
|
||||
@ -571,7 +573,7 @@ public class GoogleCloudStorage : BaseStorage
|
||||
DestinationPredefinedAcl = GetDomainACL(newdomain)
|
||||
});
|
||||
|
||||
QuotaUsedAdd(newdomain, Convert.ToInt64(obj.Size));
|
||||
await QuotaUsedAdd(newdomain, Convert.ToInt64(obj.Size));
|
||||
}
|
||||
}
|
||||
|
||||
@ -734,7 +736,7 @@ public class GoogleCloudStorage : BaseStorage
|
||||
if (QuotaController != null)
|
||||
{
|
||||
var size = await GetFileSizeAsync(domain, path);
|
||||
QuotaUsedAdd(domain, size);
|
||||
await QuotaUsedAdd(domain, size);
|
||||
}
|
||||
|
||||
return await GetUriAsync(domain, path);
|
||||
|
@ -55,8 +55,10 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
ILoggerProvider options,
|
||||
ILogger<RackspaceCloudStorage> logger,
|
||||
IHttpClientFactory httpClient)
|
||||
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options, logger, httpClient)
|
||||
IHttpClientFactory httpClient,
|
||||
TenantQuotaFeatureStatHelper tenantQuotaFeatureStatHelper,
|
||||
QuotaSocketManager quotaSocketManager)
|
||||
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options, logger, httpClient, tenantQuotaFeatureStatHelper, quotaSocketManager)
|
||||
{
|
||||
_logger = logger;
|
||||
TempPath = tempPath;
|
||||
@ -192,7 +194,7 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
return (QuotaController != null) && !domain.EndsWith("_temp");
|
||||
}
|
||||
|
||||
public Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentType,
|
||||
public async Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentType,
|
||||
string contentDisposition, ACL acl, string contentEncoding = null, int cacheDays = 5,
|
||||
DateTime? deleteAt = null, long? deleteAfter = null)
|
||||
{
|
||||
@ -282,9 +284,9 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
_region
|
||||
);
|
||||
|
||||
QuotaUsedAdd(domain, buffered.Length);
|
||||
await QuotaUsedAdd(domain, buffered.Length);
|
||||
|
||||
return GetUriAsync(domain, path);
|
||||
return await GetUriAsync(domain, path);
|
||||
|
||||
}
|
||||
|
||||
@ -296,11 +298,11 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
|
||||
client.DeleteObject(_private_container, MakePath(domain, path));
|
||||
|
||||
QuotaUsedDelete(domain, size);
|
||||
await QuotaUsedDelete(domain, size);
|
||||
|
||||
}
|
||||
|
||||
public override Task DeleteFilesAsync(string domain, string folderPath, string pattern, bool recursive)
|
||||
public override async Task DeleteFilesAsync(string domain, string folderPath, string pattern, bool recursive)
|
||||
{
|
||||
var client = GetClient();
|
||||
|
||||
@ -309,7 +311,7 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
|
||||
if (!files.Any())
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var file in files)
|
||||
@ -319,10 +321,8 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
|
||||
if (QuotaController != null)
|
||||
{
|
||||
QuotaUsedDelete(domain, files.Select(x => x.Bytes).Sum());
|
||||
await QuotaUsedDelete(domain, files.Select(x => x.Bytes).Sum());
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task DeleteFilesAsync(string domain, List<string> paths)
|
||||
@ -371,11 +371,11 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
|
||||
if (quotaUsed > 0)
|
||||
{
|
||||
QuotaUsedDelete(domain, quotaUsed);
|
||||
await QuotaUsedDelete(domain, quotaUsed);
|
||||
}
|
||||
}
|
||||
|
||||
public override Task DeleteFilesAsync(string domain, string folderPath, DateTime fromDate, DateTime toDate)
|
||||
public override async Task DeleteFilesAsync(string domain, string folderPath, DateTime fromDate, DateTime toDate)
|
||||
{
|
||||
var client = GetClient();
|
||||
|
||||
@ -384,7 +384,7 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
|
||||
if (!files.Any())
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var file in files)
|
||||
@ -394,10 +394,8 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
|
||||
if (QuotaController != null)
|
||||
{
|
||||
QuotaUsedDelete(domain, files.Select(x => x.Bytes).Sum());
|
||||
await QuotaUsedDelete(domain, files.Select(x => x.Bytes).Sum());
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task MoveDirectoryAsync(string srcdomain, string srcdir, string newdomain, string newdir)
|
||||
@ -429,8 +427,8 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
|
||||
await DeleteAsync(srcdomain, srcpath);
|
||||
|
||||
QuotaUsedDelete(srcdomain, size);
|
||||
QuotaUsedAdd(newdomain, size, quotaCheckFileSize);
|
||||
await QuotaUsedDelete(srcdomain, size);
|
||||
await QuotaUsedAdd(newdomain, size, quotaCheckFileSize);
|
||||
|
||||
return await GetUriAsync(newdomain, newpath);
|
||||
}
|
||||
@ -475,7 +473,7 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
return IsFileAsync(domain, path);
|
||||
}
|
||||
|
||||
public override Task DeleteDirectoryAsync(string domain, string path)
|
||||
public override async Task DeleteDirectoryAsync(string domain, string path)
|
||||
{
|
||||
var client = GetClient();
|
||||
|
||||
@ -484,9 +482,8 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
foreach (var obj in objToDel)
|
||||
{
|
||||
client.DeleteObject(_private_container, obj.Name);
|
||||
QuotaUsedDelete(domain, obj.Bytes);
|
||||
await QuotaUsedDelete(domain, obj.Bytes);
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task<long> GetFileSizeAsync(string domain, string path)
|
||||
@ -571,12 +568,12 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
|
||||
client.CopyObject(_private_container, srcKey, _private_container, dstKey);
|
||||
|
||||
QuotaUsedAdd(newdomain, size);
|
||||
await QuotaUsedAdd(newdomain, size);
|
||||
|
||||
return await GetUriAsync(newdomain, newpath);
|
||||
}
|
||||
|
||||
public override Task CopyDirectoryAsync(string srcdomain, string dir, string newdomain, string newdir)
|
||||
public override async Task CopyDirectoryAsync(string srcdomain, string dir, string newdomain, string newdir)
|
||||
{
|
||||
var srckey = MakePath(srcdomain, dir);
|
||||
var dstkey = MakePath(newdomain, newdir);
|
||||
@ -588,9 +585,8 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
{
|
||||
client.CopyObject(_private_container, file.Name, _private_container, file.Name.Replace(srckey, dstkey));
|
||||
|
||||
QuotaUsedAdd(newdomain, file.Bytes);
|
||||
await QuotaUsedAdd(newdomain, file.Bytes);
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override async Task<string> SavePrivateAsync(string domain, string path, Stream stream, DateTime expires)
|
||||
@ -671,7 +667,7 @@ public class RackspaceCloudStorage : BaseStorage
|
||||
{
|
||||
var size = await GetFileSizeAsync(domain, path);
|
||||
|
||||
QuotaUsedAdd(domain, size);
|
||||
await QuotaUsedAdd(domain, size);
|
||||
}
|
||||
|
||||
return await GetUriAsync(domain, path);
|
||||
|
@ -67,8 +67,10 @@ public class S3Storage : BaseStorage
|
||||
ILoggerProvider factory,
|
||||
ILogger<S3Storage> options,
|
||||
IHttpClientFactory clientFactory,
|
||||
IConfiguration configuration)
|
||||
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, factory, options, clientFactory)
|
||||
IConfiguration configuration,
|
||||
TenantQuotaFeatureStatHelper tenantQuotaFeatureStatHelper,
|
||||
QuotaSocketManager quotaSocketManager)
|
||||
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, factory, options, clientFactory, tenantQuotaFeatureStatHelper, quotaSocketManager)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
@ -259,7 +261,7 @@ public class S3Storage : BaseStorage
|
||||
|
||||
await InvalidateCloudFrontAsync(MakePath(domain, path));
|
||||
|
||||
QuotaUsedAdd(domain, buffered.Length);
|
||||
await QuotaUsedAdd(domain, buffered.Length);
|
||||
|
||||
return await GetUriAsync(domain, path);
|
||||
}
|
||||
@ -352,7 +354,7 @@ public class S3Storage : BaseStorage
|
||||
if (QuotaController != null)
|
||||
{
|
||||
var size = await GetFileSizeAsync(domain, path);
|
||||
QuotaUsedAdd(domain, size);
|
||||
await QuotaUsedAdd(domain, size);
|
||||
}
|
||||
|
||||
return await GetUriAsync(domain, path);
|
||||
@ -407,7 +409,7 @@ public class S3Storage : BaseStorage
|
||||
|
||||
await client.DeleteObjectAsync(request);
|
||||
|
||||
QuotaUsedDelete(domain, size);
|
||||
await QuotaUsedDelete(domain, size);
|
||||
}
|
||||
|
||||
public override Task DeleteFilesAsync(string domain, List<string> paths)
|
||||
@ -467,7 +469,7 @@ public class S3Storage : BaseStorage
|
||||
|
||||
if (quotaUsed > 0)
|
||||
{
|
||||
QuotaUsedDelete(domain, quotaUsed);
|
||||
await QuotaUsedDelete(domain, quotaUsed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -493,7 +495,7 @@ public class S3Storage : BaseStorage
|
||||
|
||||
await client.DeleteObjectAsync(deleteRequest);
|
||||
|
||||
QuotaUsedDelete(domain, s3Object.Size);
|
||||
await QuotaUsedDelete(domain, s3Object.Size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -515,7 +517,7 @@ public class S3Storage : BaseStorage
|
||||
|
||||
await client.DeleteObjectAsync(deleteRequest);
|
||||
|
||||
QuotaUsedDelete(domain, s3Object.Size);
|
||||
await QuotaUsedDelete(domain, s3Object.Size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -554,8 +556,8 @@ public class S3Storage : BaseStorage
|
||||
await CopyFileAsync(client, srcKey, dstKey, newdomain, S3MetadataDirective.REPLACE);
|
||||
await DeleteAsync(srcdomain, srcpath);
|
||||
|
||||
QuotaUsedDelete(srcdomain, size);
|
||||
QuotaUsedAdd(newdomain, size, quotaCheckFileSize);
|
||||
await QuotaUsedDelete(srcdomain, size);
|
||||
await QuotaUsedAdd(newdomain, size, quotaCheckFileSize);
|
||||
|
||||
return await GetUriAsync(newdomain, newpath);
|
||||
}
|
||||
@ -848,7 +850,7 @@ public class S3Storage : BaseStorage
|
||||
using var client = GetClient();
|
||||
await CopyFileAsync(client, srcKey, dstKey, newdomain, S3MetadataDirective.REPLACE);
|
||||
|
||||
QuotaUsedAdd(newdomain, size);
|
||||
await QuotaUsedAdd(newdomain, size);
|
||||
|
||||
return await GetUriAsync(newdomain, newpath);
|
||||
}
|
||||
@ -866,7 +868,7 @@ public class S3Storage : BaseStorage
|
||||
{
|
||||
await CopyFileAsync(client, s3Object.Key, s3Object.Key.Replace(srckey, dstkey), newdomain);
|
||||
|
||||
QuotaUsedAdd(newdomain, s3Object.Size);
|
||||
await QuotaUsedAdd(newdomain, s3Object.Size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ public class ChunkZipWriteOperator : IDataWriteOperator
|
||||
theMemStream.Position = 0;
|
||||
if (bytesRead == chunkUploadSize || last)
|
||||
{
|
||||
if (_fileStream.Position == _fileStream.Length)
|
||||
if (_fileStream.Position == _fileStream.Length && last)
|
||||
{
|
||||
_chunkedUploadSession.LastChunk = true;
|
||||
}
|
||||
|
@ -89,12 +89,47 @@ public class S3ZipWriteOperator : IDataWriteOperator
|
||||
{
|
||||
var fs = _fileStream;
|
||||
_fileStream = null;
|
||||
Computehash(fs, false);
|
||||
Upload(fs);
|
||||
SplitAndUpload(fs);
|
||||
}
|
||||
}
|
||||
|
||||
private void Computehash(Stream stream, bool last)
|
||||
private void SplitAndUpload(Stream stream, bool last = false)
|
||||
{
|
||||
stream.Position = 0;
|
||||
var buffer = new byte[_sessionHolder.MaxChunkUploadSize];
|
||||
|
||||
int bytesRead;
|
||||
|
||||
while ((bytesRead = stream.Read(buffer, 0, (int)_sessionHolder.MaxChunkUploadSize)) > 0)
|
||||
{
|
||||
var tempStream = _tempStream.Create();
|
||||
|
||||
tempStream.Write(buffer, 0, bytesRead);
|
||||
if (tempStream.Length == _sessionHolder.MaxChunkUploadSize)
|
||||
{
|
||||
tempStream.Position = 0;
|
||||
ComputeHash(tempStream, false);
|
||||
Upload(tempStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (last)
|
||||
{
|
||||
ComputeHash(tempStream, last);
|
||||
Upload(tempStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
tempStream.Position = tempStream.Length;
|
||||
_fileStream = tempStream;
|
||||
_gZipOutputStream.baseOutputStream_ = _fileStream;
|
||||
}
|
||||
}
|
||||
}
|
||||
stream.Dispose();
|
||||
}
|
||||
|
||||
private void ComputeHash(Stream stream, bool last)
|
||||
{
|
||||
stream.Position = 0;
|
||||
var buffer = new byte[_sessionHolder.MaxChunkUploadSize];
|
||||
@ -134,8 +169,7 @@ public class S3ZipWriteOperator : IDataWriteOperator
|
||||
_tarOutputStream.Close();
|
||||
_tarOutputStream.Dispose();
|
||||
|
||||
Computehash(_fileStream, true);
|
||||
Upload(_fileStream);
|
||||
SplitAndUpload(_fileStream, true);
|
||||
|
||||
Task.WaitAll(_tasks.ToArray());
|
||||
|
||||
|
@ -57,8 +57,8 @@ public class Feed
|
||||
public string ContextId { get; set; }
|
||||
public bool IsAllDayEvent { get; set; }
|
||||
|
||||
// это значит, что новость может обновляться (пр. добавление комментариев);
|
||||
// следовательно и права доступа могут устаревать
|
||||
// this means that the news can be updated (eg adding comments);
|
||||
// hence permissions may be outdated
|
||||
public bool Variate { get; private set; }
|
||||
|
||||
public Feed() { }
|
||||
|
@ -38,6 +38,5 @@ public class FeedApiFilter
|
||||
public Guid Author { get; set; }
|
||||
public string[] SearchKeys { get; set; }
|
||||
public bool OnlyNew { get; set; }
|
||||
public bool WithoutMe { get; set; }
|
||||
public bool WithRelated { get; set; }
|
||||
public bool History { get; set; }
|
||||
}
|
@ -202,23 +202,58 @@ public class FeedAggregateDataProvider
|
||||
var q = feedDbContext.FeedAggregates.AsNoTracking()
|
||||
.Where(r => r.Tenant == _tenantManager.GetCurrentTenant().Id);
|
||||
|
||||
var exp = GetIdSearchExpression(filter.Id, filter.Module, filter.WithRelated);
|
||||
var feeds = filter.History ? GetFeedsAsHistoryQuery(q, filter) : GetFeedsDefaultQuery(feedDbContext, q, filter);
|
||||
|
||||
if (exp != null)
|
||||
return _mapper.Map<IEnumerable<FeedAggregate>, List<FeedResultItem>>(feeds);
|
||||
}
|
||||
|
||||
private static IQueryable<FeedAggregate> GetFeedsAsHistoryQuery(IQueryable<FeedAggregate> query, FeedApiFilter filter)
|
||||
{
|
||||
Expression<Func<FeedAggregate, bool>> exp = null;
|
||||
|
||||
ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(filter.Id);
|
||||
ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(filter.Module);
|
||||
|
||||
switch (filter.Module)
|
||||
{
|
||||
q = q.Where(exp);
|
||||
case Constants.RoomsModule:
|
||||
{
|
||||
var roomId = $"{Constants.RoomItem}_{filter.Id}";
|
||||
|
||||
exp = f => f.Id == roomId || (f.Id.StartsWith(Constants.SharedRoomItem) && f.ContextId == roomId);
|
||||
|
||||
if (filter.History)
|
||||
{
|
||||
exp = f => f.Id == roomId || f.ContextId == roomId;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Constants.FilesModule:
|
||||
exp = f => f.Id.StartsWith($"{Constants.FileItem}_{filter.Id}") || f.Id.StartsWith($"{Constants.SharedFileItem}_{filter.Id}");
|
||||
break;
|
||||
case Constants.FoldersModule:
|
||||
exp = f => f.Id == $"{Constants.FolderItem}_{filter.Id}" || f.Id.StartsWith($"{Constants.SharedFolderItem}_{filter.Id}");
|
||||
break;
|
||||
}
|
||||
|
||||
var q1 = q.Join(feedDbContext.FeedUsers, a => a.Id, b => b.FeedId, (aggregates, users) => new { aggregates, users })
|
||||
if (exp == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return query.Where(exp);
|
||||
}
|
||||
|
||||
private IQueryable<FeedAggregate> GetFeedsDefaultQuery(FeedDbContext feedDbContext, IQueryable<FeedAggregate> query, FeedApiFilter filter)
|
||||
{
|
||||
var q1 = query.Join(feedDbContext.FeedUsers, a => a.Id, b => b.FeedId, (aggregates, users) => new { aggregates, users })
|
||||
.OrderByDescending(r => r.aggregates.ModifiedDate)
|
||||
.Skip(filter.Offset)
|
||||
.Take(filter.Max);
|
||||
|
||||
if (exp == null)
|
||||
{
|
||||
q1 = q1.Where(r => r.aggregates.ModifiedBy != _authContext.CurrentAccount.ID).
|
||||
Where(r => r.users.UserId == _authContext.CurrentAccount.ID);
|
||||
}
|
||||
q1 = q1.Where(r => r.aggregates.ModifiedBy != _authContext.CurrentAccount.ID).
|
||||
Where(r => r.users.UserId == _authContext.CurrentAccount.ID);
|
||||
|
||||
if (filter.OnlyNew)
|
||||
{
|
||||
@ -249,16 +284,14 @@ public class FeedAggregateDataProvider
|
||||
if (filter.SearchKeys != null && filter.SearchKeys.Length > 0)
|
||||
{
|
||||
var keys = filter.SearchKeys
|
||||
.Where(s => !string.IsNullOrEmpty(s))
|
||||
.Select(s => s.Replace("\\", "\\\\").Replace("%", "\\%").Replace("_", "\\_"))
|
||||
.ToList();
|
||||
.Where(s => !string.IsNullOrEmpty(s))
|
||||
.Select(s => s.Replace("\\", "\\\\").Replace("%", "\\%").Replace("_", "\\_"))
|
||||
.ToList();
|
||||
|
||||
q1 = q1.Where(r => keys.Any(k => r.aggregates.Keywords.StartsWith(k)));
|
||||
}
|
||||
|
||||
var news = q1.Select(r => r.aggregates).Distinct().AsEnumerable();
|
||||
|
||||
return _mapper.Map<IEnumerable<FeedAggregate>, List<FeedResultItem>>(news);
|
||||
return q1.Select(r => r.aggregates).Distinct();
|
||||
}
|
||||
|
||||
public int GetNewFeedsCount(DateTime lastReadedTime)
|
||||
@ -323,30 +356,30 @@ public class FeedAggregateDataProvider
|
||||
|
||||
if (string.IsNullOrEmpty(id) || string.IsNullOrEmpty(module))
|
||||
{
|
||||
return exp;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (module == Constants.RoomsModule)
|
||||
switch (module)
|
||||
{
|
||||
var roomId = $"{Constants.RoomItem}_{id}";
|
||||
var sharedRoomId = $"{Constants.SharedRoomItem}_{id}";
|
||||
case Constants.RoomsModule:
|
||||
{
|
||||
var roomId = $"{Constants.RoomItem}_{id}";
|
||||
|
||||
exp = f => f.Id == roomId || f.Id.StartsWith(sharedRoomId);
|
||||
exp = f => f.Id == roomId || (f.Id.StartsWith(Constants.SharedRoomItem) && f.ContextId == roomId);
|
||||
|
||||
if (withRelated)
|
||||
{
|
||||
exp = f => f.Id == roomId || f.Id.StartsWith(sharedRoomId) || f.ContextId == roomId;
|
||||
}
|
||||
}
|
||||
if (withRelated)
|
||||
{
|
||||
exp = f => f.Id == roomId || f.ContextId == roomId;
|
||||
}
|
||||
|
||||
if (module == Constants.FilesModule)
|
||||
{
|
||||
exp = f => f.Id.StartsWith($"{Constants.FileItem}_{id}") || f.Id.StartsWith($"{Constants.SharedFileItem}_{id}");
|
||||
}
|
||||
|
||||
if (module == Constants.FoldersModule)
|
||||
{
|
||||
exp = f => f.Id == $"{Constants.FolderItem}_{id}" || f.Id.StartsWith($"{Constants.SharedFolderItem}_{id}");
|
||||
break;
|
||||
}
|
||||
case Constants.FilesModule:
|
||||
exp = f => f.Id.StartsWith($"{Constants.FileItem}_{id}") || f.Id.StartsWith($"{Constants.SharedFileItem}_{id}");
|
||||
break;
|
||||
case Constants.FoldersModule:
|
||||
exp = f => f.Id == $"{Constants.FolderItem}_{id}" || f.Id.StartsWith($"{Constants.SharedFolderItem}_{id}");
|
||||
break;
|
||||
}
|
||||
|
||||
return exp;
|
||||
|
@ -1,10 +1,10 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// Этот код создан программой.
|
||||
// Исполняемая версия:4.0.30319.42000
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
|
||||
// повторной генерации кода.
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@ -13,12 +13,12 @@ namespace ASC.Migration.Resources {
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// Этот класс создан автоматически классом StronglyTypedResourceBuilder
|
||||
// с помощью такого средства, как ResGen или Visual Studio.
|
||||
// Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
|
||||
// с параметром /str или перестройте свой проект VS.
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
@ -33,7 +33,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
@ -47,8 +47,8 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Перезаписывает свойство CurrentUICulture текущего потока для всех
|
||||
/// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
@ -61,7 +61,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Clearing temporary data.
|
||||
/// Looks up a localized string similar to Clearing temporary data.
|
||||
/// </summary>
|
||||
internal static string ClearingTemporaryData {
|
||||
get {
|
||||
@ -70,7 +70,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Data processing....
|
||||
/// Looks up a localized string similar to Data processing....
|
||||
/// </summary>
|
||||
internal static string DataProcessing {
|
||||
get {
|
||||
@ -79,7 +79,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Data processing completed.
|
||||
/// Looks up a localized string similar to Data processing completed.
|
||||
/// </summary>
|
||||
internal static string DataProcessingCompleted {
|
||||
get {
|
||||
@ -88,7 +88,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Database parsing.
|
||||
/// Looks up a localized string similar to Database parsing.
|
||||
/// </summary>
|
||||
internal static string DumpParse {
|
||||
get {
|
||||
@ -97,7 +97,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Mail`s Contacts.
|
||||
/// Looks up a localized string similar to Mail`s Contacts.
|
||||
/// </summary>
|
||||
internal static string GoogleModuleNameContacts {
|
||||
get {
|
||||
@ -106,7 +106,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Google Drive`s Files.
|
||||
/// Looks up a localized string similar to Google Drive`s Files.
|
||||
/// </summary>
|
||||
internal static string GoogleModuleNameDocuments {
|
||||
get {
|
||||
@ -115,7 +115,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Group migration {0} ({1}/{2}).
|
||||
/// Looks up a localized string similar to Group migration {0} ({1}/{2}).
|
||||
/// </summary>
|
||||
internal static string GroupMigration {
|
||||
get {
|
||||
@ -124,7 +124,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Migrating user contacts {0} ({1}/{2}).
|
||||
/// Looks up a localized string similar to Migrating user contacts {0} ({1}/{2}).
|
||||
/// </summary>
|
||||
internal static string MigratingUserContacts {
|
||||
get {
|
||||
@ -133,7 +133,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Migrating user files {0} ({1}/{2}).
|
||||
/// Looks up a localized string similar to Migrating user files {0} ({1}/{2}).
|
||||
/// </summary>
|
||||
internal static string MigratingUserFiles {
|
||||
get {
|
||||
@ -142,7 +142,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Migration canceled.
|
||||
/// Looks up a localized string similar to Migration canceled.
|
||||
/// </summary>
|
||||
internal static string MigrationCanceled {
|
||||
get {
|
||||
@ -151,7 +151,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Migration completed.
|
||||
/// Looks up a localized string similar to Migration completed.
|
||||
/// </summary>
|
||||
internal static string MigrationCompleted {
|
||||
get {
|
||||
@ -160,7 +160,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Calendar.
|
||||
/// Looks up a localized string similar to Calendar.
|
||||
/// </summary>
|
||||
internal static string ModuleNameCalendar {
|
||||
get {
|
||||
@ -169,7 +169,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Groups.
|
||||
/// Looks up a localized string similar to Groups.
|
||||
/// </summary>
|
||||
internal static string ModuleNameGroups {
|
||||
get {
|
||||
@ -178,7 +178,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Mail.
|
||||
/// Looks up a localized string similar to Mail.
|
||||
/// </summary>
|
||||
internal static string ModuleNameMail {
|
||||
get {
|
||||
@ -187,7 +187,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Users.
|
||||
/// Looks up a localized string similar to Users.
|
||||
/// </summary>
|
||||
internal static string ModuleNameUsers {
|
||||
get {
|
||||
@ -196,7 +196,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Contacts.
|
||||
/// Looks up a localized string similar to Contacts.
|
||||
/// </summary>
|
||||
internal static string NextcloudModuleNameContacts {
|
||||
get {
|
||||
@ -205,7 +205,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на User`s Files.
|
||||
/// Looks up a localized string similar to User`s Files.
|
||||
/// </summary>
|
||||
internal static string NextcloudModuleNameDocuments {
|
||||
get {
|
||||
@ -214,7 +214,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Calendar.
|
||||
/// Looks up a localized string similar to Calendar.
|
||||
/// </summary>
|
||||
internal static string OnlyofficeModuleNameCalendar {
|
||||
get {
|
||||
@ -223,7 +223,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Documents.
|
||||
/// Looks up a localized string similar to Documents.
|
||||
/// </summary>
|
||||
internal static string OnlyofficeModuleNameDocuments {
|
||||
get {
|
||||
@ -232,7 +232,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Mail.
|
||||
/// Looks up a localized string similar to Mail.
|
||||
/// </summary>
|
||||
internal static string OnlyofficeModuleNameMail {
|
||||
get {
|
||||
@ -241,7 +241,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на People.
|
||||
/// Looks up a localized string similar to People.
|
||||
/// </summary>
|
||||
internal static string OnlyofficeModuleNamePeople {
|
||||
get {
|
||||
@ -250,7 +250,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Preparing for migration.
|
||||
/// Looks up a localized string similar to Preparing for migration.
|
||||
/// </summary>
|
||||
internal static string PreparingForMigration {
|
||||
get {
|
||||
@ -259,7 +259,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Starting data processing....
|
||||
/// Looks up a localized string similar to Starting data processing....
|
||||
/// </summary>
|
||||
internal static string StartOfDataProcessing {
|
||||
get {
|
||||
@ -268,7 +268,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Unzipping....
|
||||
/// Looks up a localized string similar to Unzipping....
|
||||
/// </summary>
|
||||
internal static string Unzipping {
|
||||
get {
|
||||
@ -277,7 +277,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Unzipping completed....
|
||||
/// Looks up a localized string similar to Unzipping completed....
|
||||
/// </summary>
|
||||
internal static string UnzippingFinished {
|
||||
get {
|
||||
@ -286,7 +286,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на User calendar migration {0} ({1}/{2}).
|
||||
/// Looks up a localized string similar to User calendar migration {0} ({1}/{2}).
|
||||
/// </summary>
|
||||
internal static string UserCalendarMigration {
|
||||
get {
|
||||
@ -295,7 +295,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на User migration {0} ({1}/{2}).
|
||||
/// Looks up a localized string similar to User migration {0} ({1}/{2}).
|
||||
/// </summary>
|
||||
internal static string UserMigration {
|
||||
get {
|
||||
@ -304,7 +304,7 @@ namespace ASC.Migration.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ищет локализованную строку, похожую на Failed to import user: {0} ({1}/{2}).
|
||||
/// Looks up a localized string similar to Failed to import user: {0} ({1}/{2}).
|
||||
/// </summary>
|
||||
internal static string UserSkipped {
|
||||
get {
|
||||
|
@ -45,11 +45,21 @@
|
||||
files.markAsNewFile(req.body);
|
||||
res.end();
|
||||
});
|
||||
|
||||
|
||||
router.post("/markasnew-folder", (req, res) => {
|
||||
files.markAsNewFolder(req.body);
|
||||
res.end();
|
||||
});
|
||||
|
||||
router.post("/change-quota-used-value", (req, res) => {
|
||||
files.changeQuotaUsedValue(req.body);
|
||||
res.end();
|
||||
});
|
||||
|
||||
router.post("/change-quota-feature-value", (req, res) => {
|
||||
files.changeQuotaFeatureValue(req.body);
|
||||
res.end();
|
||||
});
|
||||
|
||||
return router;
|
||||
};
|
||||
|
@ -55,11 +55,11 @@
|
||||
);
|
||||
});
|
||||
|
||||
socket.on("subscribe", ({roomParts, individual}) => {
|
||||
socket.on("subscribe", ({ roomParts, individual }) => {
|
||||
changeSubscription(roomParts, individual, subscribe);
|
||||
});
|
||||
|
||||
socket.on("unsubscribe", ({roomParts, individual}) => {
|
||||
socket.on("unsubscribe", ({ roomParts, individual }) => {
|
||||
changeSubscription(roomParts, individual, unsubscribe);
|
||||
});
|
||||
|
||||
@ -80,7 +80,7 @@
|
||||
|
||||
changeFunc(roomParts);
|
||||
|
||||
if(individual){
|
||||
if (individual) {
|
||||
if (Array.isArray(roomParts)) {
|
||||
changeFunc(roomParts.map((p) => `${p}-${userId}`));
|
||||
} else {
|
||||
@ -116,7 +116,6 @@
|
||||
socket.leave(room);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function startEdit({ fileId, room } = {}) {
|
||||
@ -167,11 +166,34 @@
|
||||
logger.info(`markAsNewFile ${fileId} in room ${room}:${count}`);
|
||||
filesIO.to(room).emit("s:markasnew-file", { fileId, count });
|
||||
}
|
||||
|
||||
|
||||
function markAsNewFolder({ folderId, count, room } = {}) {
|
||||
logger.info(`markAsNewFolder ${folderId} in room ${room}:${count}`);
|
||||
filesIO.to(room).emit("s:markasnew-folder", { folderId, count });
|
||||
}
|
||||
|
||||
return { startEdit, stopEdit, createFile, createFolder, deleteFile, deleteFolder, updateFile, updateFolder, markAsNewFile, markAsNewFolder };
|
||||
function changeQuotaUsedValue({ featureId, value, room } = {}) {
|
||||
logger.info(`changeQuotaUsedValue in room ${room}`, { featureId, value });
|
||||
filesIO.to(room).emit("s:change-quota-used-value", { featureId, value });
|
||||
}
|
||||
|
||||
function changeQuotaFeatureValue({ featureId, value, room } = {}) {
|
||||
logger.info(`changeQuotaFeatureValue in room ${room}`, { featureId, value });
|
||||
filesIO.to(room).emit("s:change-quota-feature-value", { featureId, value });
|
||||
}
|
||||
|
||||
return {
|
||||
startEdit,
|
||||
stopEdit,
|
||||
createFile,
|
||||
createFolder,
|
||||
deleteFile,
|
||||
deleteFolder,
|
||||
updateFile,
|
||||
updateFolder,
|
||||
markAsNewFile,
|
||||
markAsNewFolder,
|
||||
changeQuotaUsedValue,
|
||||
changeQuotaFeatureValue,
|
||||
};
|
||||
};
|
||||
|
@ -28,7 +28,10 @@ const accessKeyId = aws.accessKeyId;
|
||||
const secretAccessKey = aws.secretAccessKey;
|
||||
const awsRegion = aws.region;
|
||||
const logGroupName = aws.logGroupName;
|
||||
const logStreamName = aws.logStreamName;
|
||||
const logStreamName = aws.logStreamName.replace("${hostname}", os.hostname())
|
||||
.replace("${applicationContext}", "SocketIO")
|
||||
.replace("${guid}", randomUUID())
|
||||
.replace("${date}", date.format(new Date(), 'YYYY/MM/DDTHH.mm.ss'));
|
||||
|
||||
if (!fs.existsSync(dirName)) {
|
||||
fs.mkdirSync(dirName);
|
||||
@ -54,17 +57,7 @@ var options = {
|
||||
cloudWatch: {
|
||||
name: 'aws',
|
||||
level: "debug",
|
||||
logStreamName: () => {
|
||||
const hostname = os.hostname();
|
||||
const now = new Date();
|
||||
const guid = randomUUID();
|
||||
const dateAsString = date.format(now, 'YYYY/MM/DDTHH.mm.ss');
|
||||
|
||||
return logStreamName.replace("${hostname}", hostname)
|
||||
.replace("${applicationContext}", "SocketIO")
|
||||
.replace("${guid}", guid)
|
||||
.replace("${date}", dateAsString);
|
||||
},
|
||||
logStreamName: logStreamName,
|
||||
logGroupName: logGroupName,
|
||||
awsRegion: awsRegion,
|
||||
jsonMessage: true,
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2021
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2023
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
@ -12,148 +12,64 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || "development";
|
||||
|
||||
const fs = require("fs"),
|
||||
http = require("http"),
|
||||
express = require("express"),
|
||||
morgan = require("morgan"),
|
||||
cookieParser = require("cookie-parser"),
|
||||
bodyParser = require("body-parser"),
|
||||
session = require("express-session"),
|
||||
winston = require("winston"),
|
||||
WinstonCloudWatch = require('winston-cloudwatch'),
|
||||
config = require("./config").get(),
|
||||
path = require("path"),
|
||||
exphbs = require("express-handlebars"),
|
||||
favicon = require("serve-favicon"),
|
||||
cors = require("cors"),
|
||||
{ randomUUID } = require('crypto'),
|
||||
date = require('date-and-time'),
|
||||
os = require("os");
|
||||
const http = require("http"),
|
||||
express = require("express"),
|
||||
morgan = require("morgan"),
|
||||
cookieParser = require("cookie-parser"),
|
||||
bodyParser = require("body-parser"),
|
||||
session = require("express-session"),
|
||||
winston = require("./app/log.js"),
|
||||
config = require("./config").get(),
|
||||
path = require("path"),
|
||||
exphbs = require("express-handlebars"),
|
||||
favicon = require("serve-favicon"),
|
||||
cors = require("cors");
|
||||
|
||||
require('winston-daily-rotate-file');
|
||||
winston.stream = {
|
||||
write: (message) => winston.info(message),
|
||||
};
|
||||
|
||||
const app = express();
|
||||
|
||||
let logpath = config["logPath"];
|
||||
if(logpath != null)
|
||||
{
|
||||
if(!path.isAbsolute(logpath))
|
||||
{
|
||||
logpath = path.join(__dirname, logpath);
|
||||
}
|
||||
// ensure log directory exists
|
||||
fs.existsSync(logpath) || fs.mkdirSync(logpath);
|
||||
}
|
||||
|
||||
const aws = config["aws"].cloudWatch;
|
||||
|
||||
const accessKeyId = aws.accessKeyId;
|
||||
const secretAccessKey = aws.secretAccessKey;
|
||||
const awsRegion = aws.region;
|
||||
const logGroupName = aws.logGroupName;
|
||||
const logStreamName = aws.logStreamName;
|
||||
|
||||
let transports = [];
|
||||
|
||||
if (config.logger.file) {
|
||||
let logDir = logpath ? logpath : (config.app.logDir[0] === "." ? path.join(__dirname, config.app.logDir) : config.app.logDir);
|
||||
config.logger.file.filename = path.join(logDir, config.app.logName);
|
||||
transports.push(new (winston.transports.DailyRotateFile)(config.logger.file));
|
||||
}
|
||||
|
||||
if (config.logger.console) {
|
||||
transports.push(new (winston.transports.Console)(config.logger.console));
|
||||
}
|
||||
|
||||
if (aws != null && aws.accessKeyId !== '')
|
||||
{
|
||||
transports.push(new WinstonCloudWatch({
|
||||
name: 'aws',
|
||||
level: "debug",
|
||||
logStreamName: () => {
|
||||
const hostname = os.hostname();
|
||||
const now = new Date();
|
||||
const guid = randomUUID();
|
||||
const dateAsString = date.format(now, 'YYYY/MM/DDTHH.mm.ss');
|
||||
|
||||
return logStreamName.replace("${hostname}", hostname)
|
||||
.replace("${applicationContext}", "SsoAuth")
|
||||
.replace("${guid}", guid)
|
||||
.replace("${date}", dateAsString);
|
||||
},
|
||||
logGroupName: logGroupName,
|
||||
awsRegion: awsRegion,
|
||||
jsonMessage: true,
|
||||
awsOptions: {
|
||||
credentials: {
|
||||
accessKeyId: accessKeyId,
|
||||
secretAccessKey: secretAccessKey
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
const customFormat = winston.format(info => {
|
||||
const now = new Date();
|
||||
|
||||
info.date = date.format(now, 'YYYY-MM-DD HH:mm:ss');
|
||||
info.applicationContext = "SsoAuth";
|
||||
info.level = info.level.toUpperCase();
|
||||
|
||||
const hostname = os.hostname();
|
||||
|
||||
info["instance-id"] = hostname;
|
||||
|
||||
return info;
|
||||
})();
|
||||
|
||||
|
||||
let logger = winston.createLogger({
|
||||
format: winston.format.combine(
|
||||
customFormat,
|
||||
winston.format.json()
|
||||
),
|
||||
transports: transports,
|
||||
exitOnError: false
|
||||
});
|
||||
|
||||
logger.stream = {
|
||||
write: function(message) {
|
||||
logger.info(message.trim());
|
||||
}
|
||||
};
|
||||
|
||||
// view engine setup
|
||||
app.set("views", path.join(__dirname, "views"));
|
||||
app.engine("handlebars", exphbs({ defaultLayout: "main" }));
|
||||
app.set("view engine", "handlebars");
|
||||
|
||||
app.use(favicon(path.join(__dirname, "public", "favicon.ico")))
|
||||
.use(morgan("combined", { "stream": logger.stream }))
|
||||
.use(cookieParser())
|
||||
.use(bodyParser.json())
|
||||
.use(bodyParser.urlencoded({ extended: false }))
|
||||
.use(session(
|
||||
{
|
||||
resave: true,
|
||||
saveUninitialized: true,
|
||||
secret: config["core"].machinekey ? config["core"].machinekey : config.app.machinekey
|
||||
}))
|
||||
.use(cors());
|
||||
const machineKey = config["core"].machinekey
|
||||
? config["core"].machinekey
|
||||
: config.app.machinekey;
|
||||
|
||||
require("./app/middleware/saml")(app, config, logger);
|
||||
require("./app/routes")(app, config, logger);
|
||||
app
|
||||
.use(favicon(path.join(__dirname, "public", "favicon.ico")))
|
||||
.use(morgan("combined", { stream: winston.stream }))
|
||||
.use(cookieParser())
|
||||
.use(bodyParser.json())
|
||||
.use(bodyParser.urlencoded({ extended: false }))
|
||||
.use(
|
||||
session({
|
||||
resave: true,
|
||||
saveUninitialized: true,
|
||||
secret: machineKey,
|
||||
})
|
||||
)
|
||||
.use(cors());
|
||||
|
||||
require("./app/middleware/saml")(app, config);
|
||||
require("./app/routes")(app, config);
|
||||
|
||||
const httpServer = http.createServer(app);
|
||||
|
||||
httpServer.listen(config.app.port,
|
||||
function () {
|
||||
logger.info(`Start SSO Service Provider listening on port ${config.app.port} for http`);
|
||||
});
|
||||
httpServer.listen(config.app.port, function () {
|
||||
winston.info(
|
||||
`Start SSO Service Provider listening on port ${config.app.port} ` +
|
||||
`machineKey='${machineKey}' ` +
|
||||
`appsettings path='${config.app.appsettings}'`
|
||||
);
|
||||
});
|
||||
|
101
common/ASC.SsoAuth/app/log.js
Normal file
101
common/ASC.SsoAuth/app/log.js
Normal file
@ -0,0 +1,101 @@
|
||||
const winston = require("winston"),
|
||||
WinstonCloudWatch = require("winston-cloudwatch");
|
||||
|
||||
require("winston-daily-rotate-file");
|
||||
|
||||
const path = require("path");
|
||||
const config = require("../config");
|
||||
const fs = require("fs");
|
||||
const os = require("os");
|
||||
const { randomUUID } = require("crypto");
|
||||
const date = require("date-and-time");
|
||||
|
||||
let logpath = config.get("logPath");
|
||||
if (logpath != null) {
|
||||
if (!path.isAbsolute(logpath)) {
|
||||
logpath = path.join(__dirname, "..", logpath);
|
||||
}
|
||||
}
|
||||
|
||||
const fileName = logpath
|
||||
? path.join(logpath, "web.sso.%DATE%.log")
|
||||
: path.join(__dirname, "..", "..", "..", "Logs", "web.sso.%DATE%.log");
|
||||
const dirName = path.dirname(fileName);
|
||||
|
||||
const aws = config.get("aws").cloudWatch;
|
||||
|
||||
const accessKeyId = aws.accessKeyId;
|
||||
const secretAccessKey = aws.secretAccessKey;
|
||||
const awsRegion = aws.region;
|
||||
const logGroupName = aws.logGroupName;
|
||||
const logStreamName = aws.logStreamName
|
||||
.replace("${hostname}", os.hostname())
|
||||
.replace("${applicationContext}", "SsoAuth")
|
||||
.replace("${guid}", randomUUID())
|
||||
.replace("${date}", date.format(new Date(), "YYYY/MM/DDTHH.mm.ss"));
|
||||
|
||||
if (!fs.existsSync(dirName)) {
|
||||
fs.mkdirSync(dirName);
|
||||
}
|
||||
|
||||
var options = {
|
||||
file: {
|
||||
filename: fileName,
|
||||
datePattern: "MM-DD",
|
||||
handleExceptions: true,
|
||||
humanReadableUnhandledException: true,
|
||||
zippedArchive: true,
|
||||
maxSize: "50m",
|
||||
maxFiles: "30d",
|
||||
json: true,
|
||||
},
|
||||
console: {
|
||||
level: "debug",
|
||||
handleExceptions: true,
|
||||
json: false,
|
||||
colorize: true,
|
||||
},
|
||||
cloudWatch: {
|
||||
name: "aws",
|
||||
level: "debug",
|
||||
logStreamName: logStreamName,
|
||||
logGroupName: logGroupName,
|
||||
awsRegion: awsRegion,
|
||||
jsonMessage: true,
|
||||
awsOptions: {
|
||||
credentials: {
|
||||
accessKeyId: accessKeyId,
|
||||
secretAccessKey: secretAccessKey,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let transports = [
|
||||
new winston.transports.Console(options.console),
|
||||
new winston.transports.DailyRotateFile(options.file),
|
||||
];
|
||||
|
||||
if (aws != null && aws.accessKeyId !== "") {
|
||||
transports.push(new WinstonCloudWatch(options.cloudWatch));
|
||||
}
|
||||
|
||||
const customFormat = winston.format((info) => {
|
||||
const now = new Date();
|
||||
|
||||
info.date = date.format(now, "YYYY-MM-DD HH:mm:ss");
|
||||
info.applicationContext = "SsoAuth";
|
||||
info.level = info.level.toUpperCase();
|
||||
|
||||
const hostname = os.hostname();
|
||||
|
||||
info["instance-id"] = hostname;
|
||||
|
||||
return info;
|
||||
})();
|
||||
|
||||
module.exports = new winston.createLogger({
|
||||
format: winston.format.combine(customFormat, winston.format.json()),
|
||||
transports: transports,
|
||||
exitOnError: false,
|
||||
});
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2021
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
@ -12,18 +12,21 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = (app, config, logger) => {
|
||||
const urlResolver = require("../utils/resolver")(logger);
|
||||
module.exports = (app, config) => {
|
||||
const logger = require("../log.js");
|
||||
const urlResolver = require("../utils/resolver")();
|
||||
const coder = require("../utils/coder");
|
||||
const converter = require("../utils/converter")(logger);
|
||||
const converter = require("../utils/converter")();
|
||||
const _ = require("lodash");
|
||||
const fetch = require("node-fetch");
|
||||
const routes = _.values(config.routes);
|
||||
const machineKey = config["core"].machinekey
|
||||
? config["core"].machinekey
|
||||
: config.app.machinekey;
|
||||
|
||||
const fetchConfig = async (req, res, next) => {
|
||||
const foundRoutes =
|
||||
@ -33,9 +36,9 @@ module.exports = (app, config, logger) => {
|
||||
})
|
||||
: [];
|
||||
|
||||
if(req.originalUrl =="/isLife") {
|
||||
res.sendStatus(200);
|
||||
return;
|
||||
if (req.originalUrl == "/isLife") {
|
||||
res.sendStatus(200);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!foundRoutes.length) {
|
||||
@ -63,7 +66,7 @@ module.exports = (app, config, logger) => {
|
||||
|
||||
const text = await response.text();
|
||||
|
||||
const ssoConfig = coder.decodeData(text);
|
||||
const ssoConfig = coder.decodeData(text, machineKey);
|
||||
|
||||
const idp = converter.toIdp(ssoConfig);
|
||||
|
||||
|
@ -17,10 +17,11 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = function (app, config, logger) {
|
||||
module.exports = function (app, config) {
|
||||
const saml = require("samlify");
|
||||
const { SamlLib: libsaml } = saml;
|
||||
const urlResolver = require("./utils/resolver")(logger);
|
||||
const logger = require("./log.js");
|
||||
const urlResolver = require("./utils/resolver")();
|
||||
const coder = require("./utils/coder");
|
||||
const urn = require("samlify/build/src/urn");
|
||||
const fetch = require("node-fetch");
|
||||
@ -32,8 +33,10 @@ module.exports = function (app, config, logger) {
|
||||
const UserModel = require("./model/user");
|
||||
const LogoutModel = require("./model/logout");
|
||||
const fs = require('fs');
|
||||
|
||||
let uploadDir = "";
|
||||
const selfSignedDomain = "myselfsigned.crt";
|
||||
const machineKey = config["core"].machinekey ? config["core"].machinekey : config.app.machinekey;
|
||||
|
||||
function verifySetting(req) {
|
||||
if (!req.providersInfo.settings.EnableSso) {
|
||||
@ -396,13 +399,14 @@ module.exports = function (app, config, logger) {
|
||||
req.providersInfo.mapping
|
||||
);
|
||||
|
||||
logger.info(`SSO User ${JSON.stringify(user)}`);
|
||||
logger.info(`SSO User ${JSON.stringify(user)} machineKey=${machineKey}`);
|
||||
|
||||
// Use the parseResult can do customized action
|
||||
const data = coder.encodeData(user);
|
||||
|
||||
const data = coder.encodeData(user, machineKey);
|
||||
|
||||
if (!data) {
|
||||
logger.error("coder.encodeData", user);
|
||||
logger.error("EncodeData response is EMPTY", user, machineKey);
|
||||
return res.redirect(
|
||||
urlResolver.getPortalAuthErrorUrl(
|
||||
req,
|
||||
@ -511,10 +515,14 @@ module.exports = function (app, config, logger) {
|
||||
|
||||
const relayState = urlResolver.getPortalAuthUrl(req);
|
||||
|
||||
const userData = coder.decodeData(req.query["data"]);
|
||||
const queryData = req.query["data"];
|
||||
|
||||
logger.info(`sendLogoutRequest: data: ${queryData} machineKey=${machineKey}`);
|
||||
|
||||
const userData = coder.decodeData(queryData, machineKey);
|
||||
|
||||
if (!userData) {
|
||||
logger.error(`coder.decodeData ${req.query["data"]}`);
|
||||
logger.error("DecodeData response is EMPTY", queryData, machineKey);
|
||||
return res.redirect(urlResolver.getPortal500Url(req));
|
||||
}
|
||||
|
||||
@ -599,11 +607,12 @@ module.exports = function (app, config, logger) {
|
||||
|
||||
const sendPortalLogout = async (user, req) => {
|
||||
try {
|
||||
const data = coder.encodeData(user);
|
||||
logger.info(`sendPortalLogout: SSO User ${JSON.stringify(user)} machineKey=${machineKey}`);
|
||||
|
||||
const data = coder.encodeData(user, machineKey);
|
||||
|
||||
if (!data) {
|
||||
const errorMessage = `EncodeData is EMPTY`;
|
||||
throw new Error(errorMessage);
|
||||
throw new Error("EncodeData response is EMPTY", user, machineKey);
|
||||
//return res.redirect(urlResolver.getPortal500Url(req));
|
||||
}
|
||||
|
||||
|
@ -17,26 +17,25 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const config = require("../../config").get(),
|
||||
hash = require("./hash");
|
||||
const hash = require("./hash");
|
||||
|
||||
var Coder = function() {
|
||||
return {
|
||||
encodeData: function(data) {
|
||||
encodeData: function(data, machinekey) {
|
||||
if (!data && typeof (data) !== "object")
|
||||
return undefined;
|
||||
|
||||
const jsonStr = JSON.stringify(data);
|
||||
const dataEncoded = hash.encode(jsonStr, config["machinekey"] ? config["core"].machinekey : config.app.machinekey);
|
||||
const dataEncoded = hash.encode(jsonStr, machinekey);
|
||||
|
||||
return dataEncoded;
|
||||
},
|
||||
|
||||
decodeData: function(data) {
|
||||
decodeData: function(data, machinekey) {
|
||||
if (!data && typeof (data) !== "string")
|
||||
return undefined;
|
||||
|
||||
const jsonStr = hash.decode(data, config["core"].machinekey ? config["core"].machinekey : config.app.machinekey);
|
||||
const jsonStr = hash.decode(data, machinekey);
|
||||
const dataDecoded = JSON.parse(jsonStr);
|
||||
|
||||
return dataDecoded;
|
||||
|
@ -25,6 +25,7 @@ const _ = require("lodash");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const minifyXML = require("minify-xml").minify;
|
||||
const logger = require("../log.js");
|
||||
|
||||
saml.setSchemaValidator(validator);
|
||||
|
||||
@ -33,7 +34,7 @@ const IdentityProvider = saml.IdentityProvider;
|
||||
|
||||
const templDir = path.join(process.cwd(),"../../common/ASC.SsoAuth", "/app/templates/");
|
||||
|
||||
module.exports = function (logger) {
|
||||
module.exports = function () {
|
||||
function removeCertHead(cert) {
|
||||
var newCert = cert;
|
||||
if (cert && cert[0] === "-") {
|
||||
@ -283,5 +284,3 @@ module.exports = function (logger) {
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
//module.exports = Converter(logger);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2021
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
@ -12,73 +12,64 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const logger = require("../log.js");
|
||||
|
||||
var Hash = function () {
|
||||
var getHashBase64 = function (str) {
|
||||
const crypto = require("crypto");
|
||||
const sha256 = crypto.createHash("sha256");
|
||||
sha256.update(str, "utf8");
|
||||
const result = sha256.digest("base64");
|
||||
return result;
|
||||
};
|
||||
var getHashBase64 = function (str) {
|
||||
const crypto = require("crypto");
|
||||
const sha256 = crypto.createHash("sha256");
|
||||
sha256.update(str, "utf8");
|
||||
const result = sha256.digest("base64");
|
||||
return result;
|
||||
};
|
||||
|
||||
return {
|
||||
encode: function(str, secret) {
|
||||
try {
|
||||
const strHash = getHashBase64(str + secret) + "?" + str;
|
||||
return {
|
||||
encode: function (str, secret) {
|
||||
try {
|
||||
const strHash = getHashBase64(str + secret) + "?" + str;
|
||||
|
||||
let data = new Buffer(strHash).toString("base64");
|
||||
let data = Buffer.from(strHash).toString("base64");
|
||||
|
||||
let cnt = 0;
|
||||
while (data.indexOf("=") !== -1) {
|
||||
cnt++;
|
||||
data = data.replace("=", "");
|
||||
}
|
||||
data = data.replace(/\+/g, "-").replace(/\//g, "_");
|
||||
|
||||
data = (data + cnt).replace(/\+/g, "-").replace(/\//g, "_");
|
||||
return data;
|
||||
} catch (ex) {
|
||||
logger?.error("hash.encode", str, secret, ex);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
decode: function (str, secret) {
|
||||
try {
|
||||
let strDecoded = Buffer.from(unescape(str), "base64").toString();
|
||||
|
||||
return data;
|
||||
const lastIndex = strDecoded.lastIndexOf("}");
|
||||
|
||||
} catch (ex) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
decode: function(str, secret) {
|
||||
try {
|
||||
|
||||
let strDecoded = Buffer.from(unescape(str), "base64").toString();
|
||||
|
||||
const lastIndex = strDecoded.lastIndexOf("}");
|
||||
|
||||
if (lastIndex + 1 < strDecoded.length) {
|
||||
strDecoded = strDecoded.substring(0, lastIndex + 1);
|
||||
}
|
||||
|
||||
const index = strDecoded.indexOf("?");
|
||||
|
||||
if (index > 0 && strDecoded[index + 1] == '{') {
|
||||
let hash = strDecoded.substring(0, index);
|
||||
let data = strDecoded.substring(index + 1);
|
||||
if(getHashBase64(data + secret) === hash)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
// Sig incorrect
|
||||
return null;
|
||||
|
||||
} catch (ex) {
|
||||
console.error("hash.decode", str, secret, ex);
|
||||
return null;
|
||||
}
|
||||
if (lastIndex + 1 < strDecoded.length) {
|
||||
strDecoded = strDecoded.substring(0, lastIndex + 1);
|
||||
}
|
||||
};
|
||||
|
||||
const index = strDecoded.indexOf("?");
|
||||
|
||||
if (index > 0 && strDecoded[index + 1] == "{") {
|
||||
let hash = strDecoded.substring(0, index);
|
||||
let data = strDecoded.substring(index + 1);
|
||||
if (getHashBase64(data + secret) === hash) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
// Sig incorrect
|
||||
return null;
|
||||
} catch (ex) {
|
||||
logger?.error("hash.decode", str, secret, ex);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = Hash();
|
||||
|
||||
|
@ -18,11 +18,11 @@
|
||||
"use strict";
|
||||
|
||||
const config = require("../../config").get(),
|
||||
// ReSharper disable once InconsistentNaming
|
||||
URL = require("url");
|
||||
logger = require("../log.js");
|
||||
URL = require("url");
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
module.exports = function (logger) {
|
||||
module.exports = function () {
|
||||
|
||||
function getBaseUrl(req) {
|
||||
const url = req.headers["x-rewriter-url"] || req.protocol + "://" + req.get("host");
|
||||
|
@ -72,7 +72,10 @@ const accessKeyId = aws.accessKeyId;
|
||||
const secretAccessKey = aws.secretAccessKey;
|
||||
const awsRegion = aws.region;
|
||||
const logGroupName = aws.logGroupName;
|
||||
const logStreamName = aws.logStreamName;
|
||||
const logStreamName = aws.logStreamName.replace("${hostname}", os.hostname())
|
||||
.replace("${applicationContext}", "WebDav")
|
||||
.replace("${guid}", randomUUID())
|
||||
.replace("${date}", date.format(new Date(), 'YYYY/MM/DDTHH.mm.ss'));
|
||||
|
||||
let transports = [
|
||||
new (winston.transports.Console)(),
|
||||
@ -85,17 +88,7 @@ if (aws != null && aws.accessKeyId !== '')
|
||||
transports.push(new WinstonCloudWatch({
|
||||
name: 'aws',
|
||||
level: "debug",
|
||||
logStreamName: () => {
|
||||
const hostname = os.hostname();
|
||||
const now = new Date();
|
||||
const guid = randomUUID();
|
||||
const dateAsString = date.format(now, 'YYYY/MM/DDTHH.mm.ss');
|
||||
|
||||
return logStreamName.replace("${hostname}", hostname)
|
||||
.replace("${applicationContext}", "WebDav")
|
||||
.replace("${guid}", guid)
|
||||
.replace("${date}", dateAsString);
|
||||
},
|
||||
logStreamName: logStreamName,
|
||||
logGroupName: logGroupName,
|
||||
awsRegion: awsRegion,
|
||||
jsonMessage: true,
|
||||
|
@ -32,7 +32,10 @@ const accessKeyId = aws.accessKeyId;
|
||||
const secretAccessKey = aws.secretAccessKey;
|
||||
const awsRegion = aws.region;
|
||||
const logGroupName = aws.logGroupName;
|
||||
const logStreamName = aws.logStreamName;
|
||||
const logStreamName = aws.logStreamName.replace("${hostname}", os.hostname())
|
||||
.replace("${applicationContext}", "WebPlugins")
|
||||
.replace("${guid}", randomUUID())
|
||||
.replace("${date}", date.format(new Date(), 'YYYY/MM/DDTHH.mm.ss'));
|
||||
|
||||
const options = {
|
||||
file: {
|
||||
@ -54,18 +57,8 @@ const options = {
|
||||
cloudWatch: {
|
||||
name: 'aws',
|
||||
level: "debug",
|
||||
logStreamName: () => {
|
||||
const hostname = os.hostname();
|
||||
const now = new Date();
|
||||
const guid = randomUUID();
|
||||
const dateAsString = date.format(now, 'YYYY/MM/DDTHH.mm.ss');
|
||||
|
||||
return logStreamName.replace("${hostname}", hostname)
|
||||
.replace("${applicationContext}", "WebPlugins")
|
||||
.replace("${guid}", guid)
|
||||
.replace("${date}", dateAsString);
|
||||
},
|
||||
logGroupName:logGroupName,
|
||||
logStreamName: logStreamName,
|
||||
logGroupName: logGroupName,
|
||||
awsRegion: awsRegion,
|
||||
jsonMessage: true,
|
||||
awsOptions: {
|
||||
|
@ -56,11 +56,26 @@ public class LocalesTest
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Save
|
||||
{
|
||||
get
|
||||
{
|
||||
bool save;
|
||||
if (bool.TryParse(Environment.GetEnvironmentVariable("SAVE"), out save))
|
||||
{
|
||||
return save;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> Workspaces { get; set; }
|
||||
public List<TranslationFile> TranslationFiles { get; set; }
|
||||
public List<JavaScriptFile> JavaScriptFiles { get; set; }
|
||||
public List<ModuleFolder> ModuleFolders { get; set; }
|
||||
public List<KeyValuePair<string, string>> NotTranslatedToasts { get; set; }
|
||||
public List<KeyValuePair<string, string>> NotTranslatedProps { get; set; }
|
||||
public List<LanguageItem> CommonTranslations { get; set; }
|
||||
public List<ParseJsonError> ParseJsonErrors { get; set; }
|
||||
public static string ConvertPathToOS { get; private set; }
|
||||
@ -68,13 +83,19 @@ public class LocalesTest
|
||||
//public List<JsonEncodingError> WrongEncodingJsonErrors { get; set; }
|
||||
|
||||
private static readonly string _md5ExcludesPath = Path.GetFullPath(Utils.ConvertPathToOS("../../../md5-excludes.json"));
|
||||
private static readonly string _spellCheckCommonExcludesPath = Path.GetFullPath(Utils.ConvertPathToOS("../../../spellcheck-excludes-common.json"));
|
||||
private static readonly string _spellCheckExcludesPath = Path.GetFullPath(Utils.ConvertPathToOS("../../../spellcheck-excludes.json"));
|
||||
|
||||
//private static string _encodingExcludesPath = "../../../encoding-excludes.json";
|
||||
|
||||
private static readonly List<string> _md5Excludes = File.Exists(_md5ExcludesPath)
|
||||
private static readonly List<string> Md5Excludes = File.Exists(_md5ExcludesPath)
|
||||
? JsonConvert.DeserializeObject<List<string>>(File.ReadAllText(_md5ExcludesPath))
|
||||
: new List<string>();
|
||||
|
||||
private static readonly List<string> SpellCheckCommonExcludes = File.Exists(_spellCheckCommonExcludesPath)
|
||||
? JsonConvert.DeserializeObject<List<string>>(File.ReadAllText(_spellCheckCommonExcludesPath))
|
||||
: new List<string>();
|
||||
|
||||
//private static List<string> encodingExcludes = File.Exists(_encodingExcludesPath)
|
||||
// ? JsonConvert.DeserializeObject<List<string>>(File.ReadAllText(_encodingExcludesPath))
|
||||
// : new List<string>();
|
||||
@ -201,7 +222,10 @@ public class LocalesTest
|
||||
"|(?<=toastr.success\\([\"`\'])(.*)(?=[\"\'`])" +
|
||||
"|(?<=toastr.warn\\([\"`\'])(.*)(?=[\"\'`])", RegexOptions.Multiline | RegexOptions.ECMAScript);
|
||||
|
||||
var notTranslatedPropsRegex = new Regex("<[\\w\\n][^>]* (title|placeholder|label|text)={?[\\\"\\'](.*)[\\\"\\']}?", RegexOptions.Multiline | RegexOptions.ECMAScript);
|
||||
|
||||
NotTranslatedToasts = new List<KeyValuePair<string, string>>();
|
||||
NotTranslatedProps = new List<KeyValuePair<string, string>>();
|
||||
|
||||
foreach (var path in javascriptFiles)
|
||||
{
|
||||
@ -219,6 +243,18 @@ public class LocalesTest
|
||||
}
|
||||
}
|
||||
|
||||
var propsMatches = notTranslatedPropsRegex.Matches(jsFileText).ToList();
|
||||
|
||||
if (propsMatches.Any())
|
||||
{
|
||||
foreach (var propsMatch in propsMatches)
|
||||
{
|
||||
var found = propsMatch.Value;
|
||||
if (!string.IsNullOrEmpty(found) && !NotTranslatedProps.Exists(t => t.Value == found))
|
||||
NotTranslatedProps.Add(new KeyValuePair<string, string>(path, found));
|
||||
}
|
||||
}
|
||||
|
||||
var matches = regexp.Matches(jsFileText);
|
||||
|
||||
var translationKeys = matches
|
||||
@ -318,7 +354,11 @@ public class LocalesTest
|
||||
|
||||
TestContext.Progress.WriteLine($"Found CommonTranslations = {CommonTranslations.Count()}. First path is '{CommonTranslations.FirstOrDefault()?.Path}'");
|
||||
|
||||
TestContext.Progress.WriteLine($"Found _md5Excludes = {_md5Excludes.Count()} Path to file '{_md5ExcludesPath}'");
|
||||
TestContext.Progress.WriteLine($"Found Md5Excludes = {Md5Excludes.Count} Path to file '{_md5ExcludesPath}'");
|
||||
|
||||
TestContext.Progress.WriteLine($"Found SpellCheckCommonExcludes = {SpellCheckCommonExcludes.Count} Path to file '{_spellCheckCommonExcludesPath}'");
|
||||
|
||||
TestContext.Progress.WriteLine($"Save spell check excludes = {Save} Path to file '{_spellCheckExcludesPath}'");
|
||||
|
||||
}
|
||||
|
||||
@ -359,7 +399,7 @@ public class LocalesTest
|
||||
var errorsCount = 0;
|
||||
var message = $"Next keys have spell check issues:\r\n\r\n";
|
||||
|
||||
//var list = new List<SpellCheckExclude>();
|
||||
var list = new List<SpellCheckExclude>();
|
||||
|
||||
var groupByLng = TranslationFiles
|
||||
.GroupBy(t => t.Language)
|
||||
@ -376,7 +416,7 @@ public class LocalesTest
|
||||
{
|
||||
var dicPaths = SpellCheck.GetDictionaryPaths(group.Language);
|
||||
|
||||
//var spellCheckExclude = new SpellCheckExclude(group.Language);
|
||||
var spellCheckExclude = new SpellCheckExclude(group.Language);
|
||||
|
||||
using (var dictionaryStream = File.OpenRead(dicPaths.DictionaryPath))
|
||||
using (var affixStream = File.OpenRead(dicPaths.AffixPath))
|
||||
@ -391,27 +431,44 @@ public class LocalesTest
|
||||
|
||||
if (result.HasProblems)
|
||||
{
|
||||
message += $"{++i}. lng='{group.Language}' file='{g.FilePath}'\r\nkey='{item.Key}' value='{item.Value}'\r\nIncorrect words:\r\n{string.Join("\r\n", result.SpellIssues.Select(issue => $"'{issue.Word}' Suggestion: '{issue.Suggestions.FirstOrDefault()}'"))}\r\n\r\n";
|
||||
var incorrectWords = result.SpellIssues
|
||||
.Where(t => !SpellCheckCommonExcludes
|
||||
.Exists(e => e.Equals(t.Word, StringComparison.InvariantCultureIgnoreCase)))
|
||||
.Select(issue => $"'{issue.Word}' " +
|
||||
$"Suggestion: '{issue.Suggestions.FirstOrDefault()}'")
|
||||
.ToList();
|
||||
|
||||
if (!incorrectWords.Any())
|
||||
continue;
|
||||
|
||||
message += $"{++i}. lng='{group.Language}' file='{g.FilePath}'\r\nkey='{item.Key}' " +
|
||||
$"value='{item.Value}'\r\nIncorrect words:\r\n" +
|
||||
$"{string.Join("\r\n", incorrectWords)}\r\n\r\n";
|
||||
errorsCount++;
|
||||
|
||||
|
||||
/*foreach (var word in result.SpellIssues
|
||||
if (Save)
|
||||
{
|
||||
foreach (var word in result.SpellIssues
|
||||
.Where(issue => issue.Suggestions.Any())
|
||||
.Select(issue => issue.Word))
|
||||
{
|
||||
if (!spellCheckExclude.Excludes.Contains(word))
|
||||
{
|
||||
spellCheckExclude.Excludes.Add(word);
|
||||
}
|
||||
}*/
|
||||
.Select(issue => issue.Word))
|
||||
{
|
||||
if (!spellCheckExclude.Excludes.Contains(word))
|
||||
{
|
||||
spellCheckExclude.Excludes.Add(word);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//spellCheckExclude.Excludes.Sort();
|
||||
|
||||
//list.Add(spellCheckExclude);
|
||||
if (Save)
|
||||
{
|
||||
spellCheckExclude.Excludes.Sort();
|
||||
|
||||
list.Add(spellCheckExclude);
|
||||
}
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
@ -420,8 +477,12 @@ public class LocalesTest
|
||||
}
|
||||
}
|
||||
|
||||
//string json = JsonConvert.SerializeObject(list, Formatting.Indented);
|
||||
//File.WriteAllText("../../../spellcheck-excludes.json", json, Encoding.UTF8);
|
||||
if (Save)
|
||||
{
|
||||
string json = JsonConvert.SerializeObject(list, Formatting.Indented);
|
||||
File.WriteAllText(_spellCheckExcludesPath, json, Encoding.UTF8);
|
||||
TestContext.Progress.WriteLine($"File spellcheck-excludes.json has been saved to '{_spellCheckExcludesPath}'");
|
||||
}
|
||||
|
||||
Assert.AreEqual(0, errorsCount, message);
|
||||
}
|
||||
@ -443,7 +504,7 @@ public class LocalesTest
|
||||
{
|
||||
var duplicatesByMD5 = TranslationFiles
|
||||
.Where(t => t.Language != "pt-BR")
|
||||
.Where(t => !_md5Excludes.Contains(t.Md5Hash))
|
||||
.Where(t => !Md5Excludes.Contains(t.Md5Hash))
|
||||
.GroupBy(t => t.Md5Hash)
|
||||
.Where(grp => grp.Count() > 1)
|
||||
.Select(grp => new { Key = grp.Key, Count = grp.Count(), Paths = grp.ToList().Select(f => f.FilePath) })
|
||||
@ -747,7 +808,10 @@ public class LocalesTest
|
||||
continue;
|
||||
}
|
||||
|
||||
var exepts = new List<string> { "Error", "Done", "Warning", "Alert", "Info" };
|
||||
|
||||
var notCommonKeys = module.AppliedJsTranslationKeys
|
||||
.Except(exepts)
|
||||
.Where(k => !k.StartsWith("Common:"))
|
||||
.OrderBy(t => t)
|
||||
.ToList();
|
||||
@ -1079,11 +1143,34 @@ public class LocalesTest
|
||||
Assert.AreEqual(0, NotTranslatedToasts.Count, message);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Category("Locales")]
|
||||
public void NotTranslatedPropsTest()
|
||||
{
|
||||
var message = $"Next text not translated props (title, placeholder, label, text):\r\n\r\n";
|
||||
|
||||
var i = 0;
|
||||
|
||||
NotTranslatedProps.GroupBy(t => t.Key)
|
||||
.Select(g => new
|
||||
{
|
||||
FilePath = g.Key,
|
||||
Values = g.ToList()
|
||||
})
|
||||
.ToList()
|
||||
.ForEach(t =>
|
||||
{
|
||||
message += $"{++i}. Path='{t.FilePath}'\r\n\r\n{string.Join("\r\n", t.Values.Select(v => v.Value))}\r\n\r\n";
|
||||
});
|
||||
|
||||
Assert.AreEqual(0, NotTranslatedProps.Count, message);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Category("Locales")]
|
||||
public void WrongTranslationVariablesTest()
|
||||
{
|
||||
var message = $"Next keys have wrong variables:\r\n\r\n";
|
||||
var message = $"Next keys have wrong or empty variables:\r\n\r\n";
|
||||
var regVariables = new Regex("\\{\\{([^\\{].?[^\\}]+)\\}\\}", RegexOptions.Compiled | RegexOptions.Multiline);
|
||||
|
||||
var groupedByLng = TranslationFiles
|
||||
@ -1092,8 +1179,8 @@ public class LocalesTest
|
||||
{
|
||||
Language = g.Key,
|
||||
TranslationsWithVariables = g.ToList()
|
||||
.SelectMany(t => t.Translations)
|
||||
.Where(k => k.Value.IndexOf("{{") != -1)
|
||||
.SelectMany(t => t.Translations)
|
||||
//.Where(k => k.Value.IndexOf("{{") != -1)
|
||||
.Select(t => new
|
||||
{
|
||||
t.Key,
|
||||
@ -1109,6 +1196,7 @@ public class LocalesTest
|
||||
var enWithVariables = groupedByLng
|
||||
.Where(t => t.Language == "en")
|
||||
.SelectMany(t => t.TranslationsWithVariables)
|
||||
.Where(t => t.Variables.Count > 0)
|
||||
.ToList();
|
||||
|
||||
var otherLanguagesWithVariables = groupedByLng
|
||||
@ -1118,11 +1206,129 @@ public class LocalesTest
|
||||
var i = 0;
|
||||
var errorsCount = 0;
|
||||
|
||||
foreach (var lng in otherLanguagesWithVariables)
|
||||
{
|
||||
foreach (var t in lng.TranslationsWithVariables)
|
||||
foreach (var enKeyWithVariables in enWithVariables)
|
||||
{
|
||||
foreach (var lng in otherLanguagesWithVariables)
|
||||
{
|
||||
var lngKey = lng.TranslationsWithVariables
|
||||
.Where(t => t.Key == enKeyWithVariables.Key)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (lngKey == null)
|
||||
{
|
||||
// wrong
|
||||
message += $"{++i}. lng='{lng.Language}' key='{enKeyWithVariables.Key}' not found\r\n\r\n";
|
||||
errorsCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (enKeyWithVariables.Variables.Count != lngKey.Variables.Count)
|
||||
{
|
||||
// wrong
|
||||
message += $"{++i}. lng='{lng.Language}' key='{lngKey.Key}' has less variables then 'en' language have " +
|
||||
$"(en={enKeyWithVariables.Variables.Count}|{lng.Language}={lngKey.Variables.Count})\r\n" +
|
||||
$"'en': '{enKeyWithVariables.Value}'\r\n'{lng.Language}': '{lngKey.Value}'\r\n\r\n";
|
||||
errorsCount++;
|
||||
}
|
||||
|
||||
if (!lngKey.Variables.All(v => enKeyWithVariables.Variables.Contains(v)))
|
||||
{
|
||||
// wrong
|
||||
message += $"{++i}. lng='{lng.Language}' key='{lngKey.Key}' has not equals variables of 'en' language have \r\n" +
|
||||
$"'{enKeyWithVariables.Value}' Variables=[{string.Join(",", enKeyWithVariables.Variables)}]\r\n" +
|
||||
$"'{lngKey.Value}' Variables=[{string.Join(",", lngKey.Variables)}]\r\n\r\n";
|
||||
errorsCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert.AreEqual(0, errorsCount, message);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Category("Locales")]
|
||||
public void WrongTranslationTagsTest()
|
||||
{
|
||||
var message = $"Next keys have wrong or empty translation's html tags:\r\n\r\n";
|
||||
var regString = "<([^>]*)>(\\s*(.+?)\\s*)</([^>/]*)>";
|
||||
|
||||
var regTags = new Regex(regString, RegexOptions.Compiled | RegexOptions.Multiline);
|
||||
|
||||
var groupedByLng = TranslationFiles
|
||||
.GroupBy(t => t.Language)
|
||||
.Select(g => new
|
||||
{
|
||||
var enKey = enWithVariables
|
||||
Language = g.Key,
|
||||
TranslationsWithTags = g.ToList()
|
||||
.SelectMany(t => t.Translations)
|
||||
//.Where(k => k.Value.IndexOf("<") != -1)
|
||||
.Select(t => new
|
||||
{
|
||||
t.Key,
|
||||
t.Value,
|
||||
Tags = regTags.Matches(t.Value)
|
||||
.Select(m => m.Groups[1]?.Value?.Trim())
|
||||
.ToList()
|
||||
})
|
||||
.ToList()
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var enWithTags = groupedByLng
|
||||
.Where(t => t.Language == "en")
|
||||
.SelectMany(t => t.TranslationsWithTags)
|
||||
.Where(t => t.Tags.Count > 0)
|
||||
.ToList();
|
||||
|
||||
var otherLanguagesWithTags = groupedByLng
|
||||
.Where(t => t.Language != "en")
|
||||
.ToList();
|
||||
|
||||
var i = 0;
|
||||
var errorsCount = 0;
|
||||
|
||||
foreach (var enKeyWithTags in enWithTags)
|
||||
{
|
||||
foreach (var lng in otherLanguagesWithTags)
|
||||
{
|
||||
var lngKey = lng.TranslationsWithTags
|
||||
.Where(t => t.Key == enKeyWithTags.Key)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (lngKey == null)
|
||||
{
|
||||
// wrong
|
||||
message += $"{++i}. lng='{lng.Language}' key='{enKeyWithTags.Key}' not found\r\n\r\n";
|
||||
errorsCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (enKeyWithTags.Tags.Count != lngKey.Tags.Count)
|
||||
{
|
||||
// wrong
|
||||
message += $"{++i}. lng='{lng.Language}' key='{lngKey.Key}' has less tags then 'en' language have " +
|
||||
$"(en={enKeyWithTags.Tags.Count}|{lng.Language}={lngKey.Tags.Count})\r\n" +
|
||||
$"'en': '{enKeyWithTags.Value}'\r\n'{lng.Language}': '{lngKey.Value}'\r\n\r\n";
|
||||
errorsCount++;
|
||||
}
|
||||
|
||||
if (!lngKey.Tags.All(v => enKeyWithTags.Tags.Contains(v)))
|
||||
{
|
||||
// wrong
|
||||
message += $"{++i}. lng='{lng.Language}' key='{lngKey.Key}' has not equals tags of 'en' language have \r\n" +
|
||||
$"'{enKeyWithTags.Value}' Tags=[{string.Join(",", enKeyWithTags.Tags)}]\r\n" +
|
||||
$"'{lngKey.Value}' Tags=[{string.Join(",", lngKey.Tags)}]\r\n\r\n";
|
||||
errorsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*foreach (var lng in otherLanguagesWithTags)
|
||||
{
|
||||
foreach (var t in lng.TranslationsWithTags)
|
||||
{
|
||||
var enKey = enWithTags
|
||||
.Where(en => en.Key == t.Key)
|
||||
.FirstOrDefault();
|
||||
|
||||
@ -1134,25 +1340,25 @@ public class LocalesTest
|
||||
continue;
|
||||
}
|
||||
|
||||
if (enKey.Variables.Count != t.Variables.Count)
|
||||
if (enKey.Tags.Count != t.Tags.Count)
|
||||
{
|
||||
// wrong
|
||||
message += $"{++i}. lng='{lng.Language}' key='{t.Key}' has less variables then 'en' language have " +
|
||||
$"(en={enKey.Variables.Count}|{lng.Language}={t.Variables.Count})\r\n" +
|
||||
message += $"{++i}. lng='{lng.Language}' key='{t.Key}' has less tags then 'en' language have " +
|
||||
$"(en={enKey.Tags.Count}|{lng.Language}={t.Tags.Count})\r\n" +
|
||||
$"'en': '{enKey.Value}'\r\n'{lng.Language}': '{t.Value}'\r\n\r\n";
|
||||
errorsCount++;
|
||||
}
|
||||
|
||||
if (!t.Variables.All(v => enKey.Variables.Contains(v)))
|
||||
if (!t.Tags.All(v => enKey.Tags.Contains(v)))
|
||||
{
|
||||
// wrong
|
||||
errorsCount++;
|
||||
message += $"{++i}. lng='{lng.Language}' key='{t.Key}' has not equals variables of 'en' language have\r\n\r\n" +
|
||||
$"Have to be:\r\n'{enKey.Value}'\r\n\r\n{string.Join("\r\n", enKey.Variables)}\r\n\r\n" +
|
||||
$"But in real:\r\n'{t.Value}'\r\n\r\n{string.Join("\r\n", t.Variables)} \r\n\r\n";
|
||||
message += $"{++i}. lng='{lng.Language}' key='{t.Key}' has not equals tags of 'en' language have\r\n\r\n" +
|
||||
$"Have to be:\r\n'{enKey.Value}'\r\n\r\n{string.Join("\r\n", enKey.Tags)}\r\n\r\n" +
|
||||
$"But in real:\r\n'{t.Value}'\r\n\r\n{string.Join("\r\n", t.Tags)} \r\n\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
Assert.AreEqual(0, errorsCount, message);
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
[
|
||||
"Amazon",
|
||||
"AWS",
|
||||
"DocSpace",
|
||||
"ONLYOFFICE",
|
||||
"ID",
|
||||
"IP",
|
||||
"IPv4",
|
||||
"IPv",
|
||||
"DNS",
|
||||
"SVG",
|
||||
"PNG",
|
||||
"NameId",
|
||||
"IdP",
|
||||
"Sp",
|
||||
"macOS",
|
||||
"SAML",
|
||||
"Stripe",
|
||||
"SDK"
|
||||
]
|
@ -102,15 +102,15 @@ public class PortalController : ControllerBase
|
||||
[HttpPost("register")]
|
||||
[AllowCrossSiteJson]
|
||||
[Authorize(AuthenticationSchemes = "auth:allowskip:registerportal")]
|
||||
public Task<IActionResult> RegisterAsync(TenantModel model)
|
||||
public async Task<IActionResult> RegisterAsync(TenantModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return Task.FromResult<IActionResult>(BadRequest(new
|
||||
return BadRequest(new
|
||||
{
|
||||
error = "portalNameEmpty",
|
||||
message = "PortalName is required"
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
@ -122,11 +122,11 @@ public class PortalController : ControllerBase
|
||||
message.Add(ModelState[k].Errors.FirstOrDefault().ErrorMessage);
|
||||
}
|
||||
|
||||
return Task.FromResult<IActionResult>(BadRequest(new
|
||||
return BadRequest(new
|
||||
{
|
||||
error = "params",
|
||||
message
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
@ -136,7 +136,7 @@ public class PortalController : ControllerBase
|
||||
if (!CheckPasswordPolicy(model.Password, out var error1))
|
||||
{
|
||||
sw.Stop();
|
||||
return Task.FromResult<IActionResult>(BadRequest(error1));
|
||||
return BadRequest(error1);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(model.Password))
|
||||
@ -152,16 +152,11 @@ public class PortalController : ControllerBase
|
||||
{
|
||||
sw.Stop();
|
||||
|
||||
return Task.FromResult<IActionResult>(BadRequest(error));
|
||||
return BadRequest(error);
|
||||
}
|
||||
|
||||
return InternalRegisterAsync(model, error, sw);
|
||||
}
|
||||
|
||||
private async Task<IActionResult> InternalRegisterAsync(TenantModel model, object error, Stopwatch sw)
|
||||
{
|
||||
model.PortalName = (model.PortalName ?? "").Trim();
|
||||
var (exists, _) = await CheckExistingNamePortalAsync(model.PortalName);
|
||||
(var exists, error) = await CheckExistingNamePortalAsync(model.PortalName);
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
|
@ -66,8 +66,8 @@ public class Startup : BaseStartup
|
||||
services.AddHostedService<BackupCleanerTempFileService>();
|
||||
|
||||
services.AddHostedService<BackupWorkerService>();
|
||||
services.AddActivePassiveHostedService<BackupCleanerService>();
|
||||
services.AddActivePassiveHostedService<BackupSchedulerService>();
|
||||
services.AddActivePassiveHostedService<BackupCleanerService>(DIHelper);
|
||||
services.AddActivePassiveHostedService<BackupSchedulerService>(DIHelper);
|
||||
|
||||
services.AddBaseDbContextPool<BackupsContext>();
|
||||
services.AddBaseDbContextPool<FilesDbContext>();
|
||||
|
@ -82,38 +82,20 @@ public abstract class FeedModule : IFeedModule
|
||||
}
|
||||
}
|
||||
|
||||
protected string GetGroupId(string item, Guid author, string rootId = null, int action = -1)
|
||||
protected string GetGroupId(string item, Guid author, DateTime date, string rootId = null, int action = -1)
|
||||
{
|
||||
const int interval = 2;
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
var hours = now.Hour;
|
||||
var groupIdHours = hours - (hours % interval);
|
||||
var time = date.ToString("g");
|
||||
|
||||
if (rootId == null)
|
||||
{
|
||||
// groupId = {item}_{author}_{date}
|
||||
return string.Format("{0}_{1}_{2}",
|
||||
item,
|
||||
author,
|
||||
now.ToString("yyyy.MM.dd.") + groupIdHours);
|
||||
return $"{item}_{author}_{time}";
|
||||
}
|
||||
|
||||
if (action == -1)
|
||||
{
|
||||
// groupId = {item}_{author}_{date}_{rootId}_{action}
|
||||
return string.Format("{0}_{1}_{2}_{3}",
|
||||
item,
|
||||
author,
|
||||
now.ToString("yyyy.MM.dd.") + groupIdHours,
|
||||
rootId);
|
||||
return $"{item}_{author}_{time}_{rootId}";
|
||||
}
|
||||
|
||||
// groupId = {item}_{author}_{date}_{rootId}_{action}
|
||||
return string.Format("{0}_{1}_{2}_{3}_{4}",
|
||||
item,
|
||||
author,
|
||||
now.ToString("yyyy.MM.dd.") + groupIdHours,
|
||||
rootId,
|
||||
action);
|
||||
|
||||
return $"{item}_{author}_{time}_{rootId}_{action}";
|
||||
}
|
||||
}
|
||||
|
@ -53,8 +53,8 @@ public class Startup : BaseWorkerStartup
|
||||
DIHelper.TryAdd<NotifyInvokeSendMethodRequestedIntegrationEventHandler>();
|
||||
DIHelper.TryAdd<NotifySendMessageRequestedIntegrationEventHandler>();
|
||||
|
||||
services.AddActivePassiveHostedService<NotifySenderService>();
|
||||
services.AddActivePassiveHostedService<NotifyCleanerService>();
|
||||
services.AddActivePassiveHostedService<NotifySenderService>(DIHelper);
|
||||
services.AddActivePassiveHostedService<NotifyCleanerService>(DIHelper);
|
||||
|
||||
services.AddBaseDbContextPool<NotifyDbContext>();
|
||||
}
|
||||
|
@ -69,15 +69,15 @@
|
||||
"enable": [ "box", "dropboxv2", "docusign", "google", "onedrive", "sharepoint", "nextcloud", "owncloud", "webdav", "kdrive" ]
|
||||
},
|
||||
"docservice": {
|
||||
"coauthor-docs": [ ".csv", ".docm", ".docx", ".docxf", ".dotm", ".dotx", ".oform", ".potm", ".potx", ".ppsm", ".pptm", ".ppsx", ".pptx", ".txt", ".xlsm", ".xlsx", ".xltm", ".xltx" ],
|
||||
"commented-docs": [ ".docm", ".docx", ".docxf", ".dotm", ".dotx", ".potm", ".potx", ".ppsm", ".pptm", ".ppsx", ".pptx", ".xlsm", ".xlsx", ".xltm", ".xltx" ],
|
||||
"convert-docs": [ ".doc", ".dot", ".dps", ".dpt", ".epub", ".et", ".ett", ".fb2", ".fodp", ".fods", ".fodt", ".htm", ".html", ".mht", ".mhtml", ".odp", ".ods", ".odt", ".otp", ".ots", ".ott", ".pot", ".pps", ".ppt", ".rtf", ".stw", ".sxc", "sxi", ".sxw", ".wps", ".wpt", ".xls", ".xlsb", ".xlt", ".xml" ],
|
||||
"edited-docs": [ "csv", ".doc", ".docm", ".docx", ".docxf", ".dot", ".dotm", ".dotx", ".dps", ".dpt", ".epub", ".et", ".ett", ".fb2", ".fodp", ".fods", ".fodt", ".htm", ".html", ".mht", ".mhtml", ".odp", ".ods", ".odt", ".oform", ".otp", ".ots", ".ott", ".pot", ".potm", ".potx", ".pps", ".ppsm", ".ppsx", ".ppt", ".pptm", ".pptx", ".rtf", ".stw", ".sxc", "sxi", ".sxw", ".txt", ".wps", ".wpt", ".xls", ".xlsb", ".xlsm", ".xlsx", ".xlt", ".xltm", ".xltx", ".xml" ],
|
||||
"encrypted-docs": [ ".docm", ".docx", ".docxf", ".dotm", ".dotx", ".oform", ".potm", ".potx", ".ppsm", ".pptm", ".ppsx", ".pptx", ".xlsm", ".xlsx", ".xltm", ".xltx" ],
|
||||
"coauthor-docs": [ ".pptx", ".ppsx", ".xlsx", ".csv", ".docx", ".docxf", ".oform", ".txt" ],
|
||||
"commented-docs": [ ".docx", ".docxf", ".xlsx", ".pptx" ],
|
||||
"convert-docs": [ ".pptm", ".ppt", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".xlsm", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".rtf", ".xml" ],
|
||||
"edited-docs": [ ".pptx", ".pptm", ".ppt", ".ppsx", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".xlsx", ".xlsm", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".csv", ".docx", ".docxf", ".oform", ".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".txt", ".rtf", ".mht", ".html", ".htm" ],
|
||||
"encrypted-docs": [ ".docx", ".docxf", ".xlsx", ".pptx", ".oform" ],
|
||||
"formfilling-docs": [ ".oform" ],
|
||||
"customfilter-docs": [ ".xlsm", ".xlsx", ".xltm", ".xltx" ],
|
||||
"reviewed-docs": [ ".docm", ".docx", ".docxf", ".dotm", ".dotx" ],
|
||||
"viewed-docs": [ ".csv", ".djvu", ".doc", ".docm", ".docx", ".docxf", ".dot", ".dotm", ".dotx", ".dps", ".dpt", ".epub", ".et", ".ett", ".fb2", ".fodp", ".fods", ".fodt", ".gdoc", ".gsheet", ".gslides", ".htm", ".html", ".mht", ".mhtml", ".odp", ".ods", ".odt", ".oform", ".otp", ".ots", ".ott", ".oxps", ".pdf", ".pot", ".potm", ".potx", ".pps", ".ppsm", ".ppsx", ".ppt", ".pptm", ".pptx", ".rtf", ".stw", ".sxc", "sxi", ".sxw", ".txt", ".wps", ".wpt", ".xls", ".xlsb", ".xlsm", ".xlsx", ".xlt", ".xltm", ".xltx", ".xml", ".xps" ],
|
||||
"customfilter-docs": [ ".xlsx" ],
|
||||
"reviewed-docs": [ ".docx", ".docxf" ],
|
||||
"viewed-docs": [ ".pptx", ".pptm", ".ppt", ".ppsx", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".gslides", ".xlsx", ".xlsm", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".gsheet", ".csv", ".docx", ".docxf", ".oform", ".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".gdoc", ".txt", ".rtf", ".mht", ".html", ".htm", ".xml", ".fb2", ".epub", ".pdf", ".djvu", ".xps", ".oxps" ],
|
||||
"secret": {
|
||||
"value": "secret",
|
||||
"header": "AuthorizationJwt"
|
||||
@ -110,6 +110,8 @@
|
||||
"min": 3,
|
||||
"max": 50
|
||||
},
|
||||
"api-system":"",
|
||||
"api-cache":"",
|
||||
"images": "static/images",
|
||||
"hide-settings": "Monitoring,LdapSettings,DocService,MailService,PublicPortal,ProxyHttpContent,SpamSubscription,FullTextSearch",
|
||||
"hub": {
|
||||
@ -120,30 +122,24 @@
|
||||
"controlpanel": {
|
||||
"url": ""
|
||||
},
|
||||
"legalterms": "https://www.onlyoffice.com/legalterms.aspx",
|
||||
"support-feedback": "https://helpdesk.onlyoffice.com",
|
||||
"teamlab-site": "http://www.onlyoffice.com",
|
||||
"help-center": "https://helpcenter.onlyoffice.com/{ru|de|fr|es|it}",
|
||||
"max-upload-size" : 5242880
|
||||
"book-training-email": "training@onlyoffice.com",
|
||||
"documentation-email": "documentation@onlyoffice.com",
|
||||
"max-upload-size" : 5242880,
|
||||
"zendesk-key" : ""
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"default": {
|
||||
"name": "default",
|
||||
"connectionString": "Server=localhost;Database=docspace;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;Connection Timeout=30;Maximum Pool Size=300;ConnectionReset=false",
|
||||
"providerName": "MySql.Data.MySqlClient"
|
||||
},
|
||||
"postgre": {
|
||||
"name": "postgre",
|
||||
"connectionString": "Host=localhost;Port=5432;Database=docspace;Username=postgres;Password=dev;",
|
||||
"providerName": "Npgsql"
|
||||
},
|
||||
"mysql": {
|
||||
"name": "mysql",
|
||||
"connectionString": "Server=localhost;Database=docspace;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;Connection Timeout=30;Maximum Pool Size=300;ConnectionReset=false",
|
||||
"providerName": "MySql.Data.MySqlClient"
|
||||
},
|
||||
"teamlabsite": {
|
||||
"name": "docspacesite",
|
||||
"connectionString": "Server=localhost;Database=docspacesite;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;Connection Timeout=30;Maximum Pool Size=300;ConnectionReset=false",
|
||||
"name": "teamlabsite",
|
||||
"connectionString": "Server=localhost;Database=teamlabsite;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;Connection Timeout=30;Maximum Pool Size=300;ConnectionReset=false",
|
||||
"providerName": "MySql.Data.MySqlClient"
|
||||
}
|
||||
},
|
||||
|
@ -150,38 +150,6 @@
|
||||
"clickatellapiKey": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "ASC.FederatedLogin.LoginProviders.DocuSignLoginProvider, ASC.FederatedLogin",
|
||||
"services": [
|
||||
{
|
||||
"type": "ASC.Core.Common.Configuration.Consumer, ASC.Core.Common"
|
||||
},
|
||||
{
|
||||
"type": "ASC.FederatedLogin.LoginProviders.DocuSignLoginProvider, ASC.FederatedLogin"
|
||||
},
|
||||
{
|
||||
"key": "docuSign",
|
||||
"type": "ASC.Core.Common.Configuration.Consumer, ASC.Core.Common"
|
||||
},
|
||||
{
|
||||
"key": "docuSign",
|
||||
"type": "ASC.FederatedLogin.LoginProviders.DocuSignLoginProvider, ASC.FederatedLogin"
|
||||
}
|
||||
],
|
||||
"instanceScope": "perlifetimescope",
|
||||
"parameters": {
|
||||
"name": "docuSign",
|
||||
"order": "1",
|
||||
"props": {
|
||||
"docuSignClientId": "",
|
||||
"docuSignClientSecret": "",
|
||||
"docuSignHost": ""
|
||||
},
|
||||
"additional": {
|
||||
"docuSignRedirectUrl" : "https://service.teamlab.info/oauth2.aspx"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "ASC.FederatedLogin.LoginProviders.DropboxLoginProvider, ASC.FederatedLogin",
|
||||
@ -338,37 +306,6 @@
|
||||
"linkedInRedirectUrl" : "https://service.teamlab.info/oauth2.aspx"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "ASC.FederatedLogin.LoginProviders.MailRuLoginProvider, ASC.FederatedLogin",
|
||||
"services": [
|
||||
{
|
||||
"type": "ASC.Core.Common.Configuration.Consumer, ASC.Core.Common"
|
||||
},
|
||||
{
|
||||
"type": "ASC.FederatedLogin.LoginProviders.MailRuLoginProvider, ASC.FederatedLogin"
|
||||
},
|
||||
{
|
||||
"key": "mailru",
|
||||
"type": "ASC.Core.Common.Configuration.Consumer, ASC.Core.Common"
|
||||
},
|
||||
{
|
||||
"key": "mailru",
|
||||
"type": "ASC.FederatedLogin.LoginProviders.MailRuLoginProvider, ASC.FederatedLogin"
|
||||
}
|
||||
],
|
||||
"instanceScope": "perlifetimescope",
|
||||
"parameters": {
|
||||
"name": "mailru",
|
||||
"order": "4",
|
||||
"props": {
|
||||
"mailRuClientId": "",
|
||||
"mailRuClientSecret": ""
|
||||
},
|
||||
"additional": {
|
||||
"mailRuRedirectUrl" : "https://service.teamlab.info/oauth2.aspx"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "ASC.FederatedLogin.LoginProviders.OneDriveLoginProvider, ASC.FederatedLogin",
|
||||
|
@ -191,7 +191,9 @@ server {
|
||||
location ~* /(authentication|modules|portal|security|settings|smtpsettings|capabilities|thirdparty|encryption|feed) {
|
||||
proxy_pass http://127.0.0.1:5000;
|
||||
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
|
||||
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
|
||||
location ~* portal/(.*)(backup|restore)(.*) {
|
||||
rewrite (.*)/portal/(.*) $1/backup/$2 break;
|
||||
proxy_redirect off;
|
||||
|
4305
i18next/client.babel
4305
i18next/client.babel
File diff suppressed because it is too large
Load Diff
1652
i18next/common.babel
1652
i18next/common.babel
File diff suppressed because it is too large
Load Diff
6
licenses.config.js
Normal file
6
licenses.config.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
isValidLicense: (license) => {
|
||||
const valid = new RegExp("\\b(mit|apache\\b.*2|bsd|isc|unlicense)\\b", "i");
|
||||
return valid.test(license);
|
||||
},
|
||||
};
|
@ -73,7 +73,7 @@ namespace ASC.Migrations.MySql.Migrations.CoreDb
|
||||
new
|
||||
{
|
||||
Tenant = -1,
|
||||
Features = "trial,audit,ldap,sso,whitelabel,thirdparty,restore,total_size:107374182400,file_size:100,manager:1",
|
||||
Features = "trial,audit,ldap,sso,whitelabel,thirdparty,restore,oauth,total_size:107374182400,file_size:100,manager:1",
|
||||
Name = "trial",
|
||||
Price = 0m,
|
||||
Visible = false
|
||||
@ -81,7 +81,7 @@ namespace ASC.Migrations.MySql.Migrations.CoreDb
|
||||
new
|
||||
{
|
||||
Tenant = -2,
|
||||
Features = "audit,ldap,sso,whitelabel,thirdparty,restore,contentsearch,total_size:107374182400,file_size:1024,manager:1",
|
||||
Features = "audit,ldap,sso,whitelabel,thirdparty,restore,oauth,contentsearch,total_size:107374182400,file_size:1024,manager:1",
|
||||
Name = "admin",
|
||||
Price = 30m,
|
||||
ProductId = "1002",
|
||||
@ -90,7 +90,7 @@ namespace ASC.Migrations.MySql.Migrations.CoreDb
|
||||
new
|
||||
{
|
||||
Tenant = -3,
|
||||
Features = "free,total_size:2147483648,manager:5,room:5",
|
||||
Features = "free,total_size:2147483648,manager:3,room:12",
|
||||
Name = "startup",
|
||||
Price = 0m,
|
||||
Visible = false
|
||||
|
@ -120,17 +120,17 @@ public partial class CoreDbContextMigrate : Migration
|
||||
migrationBuilder.InsertData(
|
||||
table: "tenants_quota",
|
||||
columns: new[] { "tenant", "description", "features", "name", "product_id" },
|
||||
values: new object[] { -3, null, "free,total_size:2147483648,manager:5,room:5", "startup", null });
|
||||
values: new object[] { -3, null, "free,total_size:2147483648,manager:3,room:12", "startup", null });
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "tenants_quota",
|
||||
columns: new[] { "tenant", "description", "features", "name", "price", "product_id", "visible" },
|
||||
values: new object[] { -2, null, "audit,ldap,sso,whitelabel,thirdparty,restore,contentsearch,total_size:107374182400,file_size:1024,manager:1", "admin", 30m, "1002", true });
|
||||
values: new object[] { -2, null, "audit,ldap,sso,whitelabel,thirdparty,restore,oauth,contentsearch,total_size:107374182400,file_size:1024,manager:1", "admin", 30m, "1002", true });
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "tenants_quota",
|
||||
columns: new[] { "tenant", "description", "features", "name", "product_id" },
|
||||
values: new object[] { -1, null, "trial,audit,ldap,sso,whitelabel,thirdparty,restore,total_size:107374182400,file_size:100,manager:1", "trial", null });
|
||||
values: new object[] { -1, null, "trial,audit,ldap,sso,whitelabel,thirdparty,restore,oauth,total_size:107374182400,file_size:100,manager:1", "trial", null });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "last_modified",
|
||||
|
@ -70,7 +70,7 @@ namespace ASC.Migrations.MySql.Migrations.CoreDb
|
||||
new
|
||||
{
|
||||
Tenant = -1,
|
||||
Features = "trial,audit,ldap,sso,whitelabel,thirdparty,restore,total_size:107374182400,file_size:100,manager:1",
|
||||
Features = "trial,audit,ldap,sso,whitelabel,thirdparty,restore,oauth,total_size:107374182400,file_size:100,manager:1",
|
||||
Name = "trial",
|
||||
Price = 0m,
|
||||
Visible = false
|
||||
@ -78,7 +78,7 @@ namespace ASC.Migrations.MySql.Migrations.CoreDb
|
||||
new
|
||||
{
|
||||
Tenant = -2,
|
||||
Features = "audit,ldap,sso,whitelabel,thirdparty,restore,contentsearch,total_size:107374182400,file_size:1024,manager:1",
|
||||
Features = "audit,ldap,sso,whitelabel,thirdparty,restore,oauth,contentsearch,total_size:107374182400,file_size:1024,manager:1",
|
||||
Name = "admin",
|
||||
Price = 30m,
|
||||
ProductId = "1002",
|
||||
@ -87,7 +87,7 @@ namespace ASC.Migrations.MySql.Migrations.CoreDb
|
||||
new
|
||||
{
|
||||
Tenant = -3,
|
||||
Features = "free,total_size:2147483648,manager:5,room:5",
|
||||
Features = "free,total_size:2147483648,manager:3,room:12",
|
||||
Name = "startup",
|
||||
Price = 0m,
|
||||
Visible = false
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -362,355 +362,412 @@ public partial class FilesDbContextMigrate : Migration
|
||||
table: "files_converts",
|
||||
columns: new[] { "input", "output" },
|
||||
values: new object[,]
|
||||
{
|
||||
{ ".csv", ".ods" },
|
||||
{ ".csv", ".ots" },
|
||||
{ ".csv", ".pdf" },
|
||||
{ ".csv", ".xlsm" },
|
||||
{ ".csv", ".xlsx" },
|
||||
{ ".csv", ".xltm" },
|
||||
{ ".csv", ".xltx" },
|
||||
{ ".doc", ".docm" },
|
||||
{ ".doc", ".docx" },
|
||||
{ ".doc", ".dotm" },
|
||||
{ ".doc", ".dotx" },
|
||||
{ ".doc", ".epub" },
|
||||
{ ".doc", ".fb2" },
|
||||
{ ".doc", ".html" },
|
||||
{ ".doc", ".odt" },
|
||||
{ ".doc", ".ott" },
|
||||
{ ".doc", ".pdf" },
|
||||
{ ".doc", ".rtf" },
|
||||
{ ".doc", ".txt" },
|
||||
{ ".docm", ".docx" },
|
||||
{ ".docm", ".dotm" },
|
||||
{ ".docm", ".dotx" },
|
||||
{ ".docm", ".epub" },
|
||||
{ ".docm", ".fb2" },
|
||||
{ ".docm", ".html" },
|
||||
{ ".docm", ".odt" },
|
||||
{ ".docm", ".ott" },
|
||||
{ ".docm", ".pdf" },
|
||||
{ ".docm", ".rtf" },
|
||||
{ ".docm", ".txt" },
|
||||
{ ".doct", ".docx" },
|
||||
{ ".docx", ".docm" },
|
||||
{ ".docx", ".docxf" },
|
||||
{ ".docx", ".dotm" },
|
||||
{ ".docx", ".dotx" },
|
||||
{ ".docx", ".epub" },
|
||||
{ ".docx", ".fb2" },
|
||||
{ ".docx", ".html" },
|
||||
{ ".docx", ".odt" },
|
||||
{ ".docx", ".ott" },
|
||||
{ ".docx", ".pdf" },
|
||||
{ ".docx", ".rtf" },
|
||||
{ ".docx", ".txt" },
|
||||
{ ".docxf", ".docx" },
|
||||
{ ".docxf", ".dotx" },
|
||||
{ ".docxf", ".epub" },
|
||||
{ ".docxf", ".fb2" },
|
||||
{ ".docxf", ".html" },
|
||||
{ ".docxf", ".odt" },
|
||||
{ ".docxf", ".oform" },
|
||||
{ ".docxf", ".ott" },
|
||||
{ ".docxf", ".pdf" },
|
||||
{ ".docxf", ".rtf" },
|
||||
{ ".docxf", ".txt" },
|
||||
{ ".dot", ".docm" },
|
||||
{ ".dot", ".docx" },
|
||||
{ ".dot", ".dotm" },
|
||||
{ ".dot", ".dotx" },
|
||||
{ ".dot", ".epub" },
|
||||
{ ".dot", ".fb2" },
|
||||
{ ".dot", ".html" },
|
||||
{ ".dot", ".odt" },
|
||||
{ ".dot", ".ott" },
|
||||
{ ".dot", ".pdf" },
|
||||
{ ".dot", ".rtf" },
|
||||
{ ".dot", ".txt" },
|
||||
{ ".dotm", ".docm" },
|
||||
{ ".dotm", ".docx" },
|
||||
{ ".dotm", ".dotx" },
|
||||
{ ".dotm", ".epub" },
|
||||
{ ".dotm", ".fb2" },
|
||||
{ ".dotm", ".html" },
|
||||
{ ".dotm", ".odt" },
|
||||
{ ".dotm", ".ott" },
|
||||
{ ".dotm", ".pdf" },
|
||||
{ ".dotm", ".rtf" },
|
||||
{ ".dotm", ".txt" },
|
||||
{ ".dotx", ".docm" },
|
||||
{ ".dotx", ".docx" },
|
||||
{ ".dotx", ".dotm" },
|
||||
{ ".dotx", ".epub" },
|
||||
{ ".dotx", ".fb2" },
|
||||
{ ".dotx", ".html" },
|
||||
{ ".dotx", ".odt" },
|
||||
{ ".dotx", ".ott" },
|
||||
{ ".dotx", ".pdf" },
|
||||
{ ".dotx", ".rtf" },
|
||||
{ ".dotx", ".txt" },
|
||||
{ ".epub", ".docm" },
|
||||
{ ".epub", ".docx" },
|
||||
{ ".epub", ".dotm" },
|
||||
{ ".epub", ".dotx" },
|
||||
{ ".epub", ".fb2" },
|
||||
{ ".epub", ".html" },
|
||||
{ ".epub", ".odt" },
|
||||
{ ".epub", ".ott" },
|
||||
{ ".epub", ".pdf" },
|
||||
{ ".epub", ".rtf" },
|
||||
{ ".epub", ".txt" },
|
||||
{ ".fb2", ".docm" },
|
||||
{ ".fb2", ".docx" },
|
||||
{ ".fb2", ".dotm" },
|
||||
{ ".fb2", ".dotx" },
|
||||
{ ".fb2", ".epub" },
|
||||
{ ".fb2", ".html" },
|
||||
{ ".fb2", ".odt" },
|
||||
{ ".fb2", ".ott" },
|
||||
{ ".fb2", ".pdf" },
|
||||
{ ".fb2", ".rtf" },
|
||||
{ ".fb2", ".txt" },
|
||||
{ ".fodp", ".odp" },
|
||||
{ ".fodp", ".otp" },
|
||||
{ ".fodp", ".pdf" },
|
||||
{ ".fodp", ".potm" },
|
||||
{ ".fodp", ".potx" },
|
||||
{ ".fodp", ".pptm" },
|
||||
{ ".fodp", ".pptx" },
|
||||
{ ".fods", ".csv" },
|
||||
{ ".fods", ".ods" },
|
||||
{ ".fods", ".ots" },
|
||||
{ ".fods", ".pdf" },
|
||||
{ ".fods", ".xlsm" },
|
||||
{ ".fods", ".xlsx" },
|
||||
{ ".fods", ".xltm" },
|
||||
{ ".fods", ".xltx" },
|
||||
{ ".fodt", ".docm" },
|
||||
{ ".fodt", ".docx" },
|
||||
{ ".fodt", ".dotm" },
|
||||
{ ".fodt", ".dotx" },
|
||||
{ ".fodt", ".epub" },
|
||||
{ ".fodt", ".fb2" },
|
||||
{ ".fodt", ".html" },
|
||||
{ ".fodt", ".odt" },
|
||||
{ ".fodt", ".ott" },
|
||||
{ ".fodt", ".pdf" },
|
||||
{ ".fodt", ".rtf" },
|
||||
{ ".fodt", ".txt" },
|
||||
{ ".html", ".docm" },
|
||||
{ ".html", ".docx" },
|
||||
{ ".html", ".dotm" },
|
||||
{ ".html", ".dotx" },
|
||||
{ ".html", ".epub" },
|
||||
{ ".html", ".fb2" },
|
||||
{ ".html", ".odt" },
|
||||
{ ".html", ".ott" },
|
||||
{ ".html", ".pdf" },
|
||||
{ ".html", ".rtf" },
|
||||
{ ".html", ".txt" },
|
||||
{ ".mht", ".docm" },
|
||||
{ ".mht", ".docx" },
|
||||
{ ".mht", ".dotm" },
|
||||
{ ".mht", ".dotx" },
|
||||
{ ".mht", ".epub" },
|
||||
{ ".mht", ".fb2" },
|
||||
{ ".mht", ".odt" },
|
||||
{ ".mht", ".ott" },
|
||||
{ ".mht", ".pdf" },
|
||||
{ ".mht", ".rtf" },
|
||||
{ ".mht", ".txt" },
|
||||
{ ".odp", ".otp" },
|
||||
{ ".odp", ".pdf" },
|
||||
{ ".odp", ".potm" },
|
||||
{ ".odp", ".potx" },
|
||||
{ ".odp", ".pptm" },
|
||||
{ ".odp", ".pptx" },
|
||||
{ ".ods", ".csv" },
|
||||
{ ".ods", ".ots" },
|
||||
{ ".ods", ".pdf" },
|
||||
{ ".ods", ".xlsm" },
|
||||
{ ".ods", ".xlsx" },
|
||||
{ ".ods", ".xltm" },
|
||||
{ ".ods", ".xltx" },
|
||||
{ ".odt", ".docm" },
|
||||
{ ".odt", ".docx" },
|
||||
{ ".odt", ".dotm" },
|
||||
{ ".odt", ".dotx" },
|
||||
{ ".odt", ".epub" },
|
||||
{ ".odt", ".fb2" },
|
||||
{ ".odt", ".html" },
|
||||
{ ".odt", ".ott" },
|
||||
{ ".odt", ".pdf" },
|
||||
{ ".odt", ".rtf" },
|
||||
{ ".odt", ".txt" },
|
||||
{ ".otp", ".odp" },
|
||||
{ ".otp", ".pdf" },
|
||||
{ ".otp", ".potm" },
|
||||
{ ".otp", ".potx" },
|
||||
{ ".otp", ".pptm" },
|
||||
{ ".otp", ".pptx" },
|
||||
{ ".ots", ".csv" },
|
||||
{ ".ots", ".ods" },
|
||||
{ ".ots", ".pdf" },
|
||||
{ ".ots", ".xlsm" },
|
||||
{ ".ots", ".xlsx" },
|
||||
{ ".ots", ".xltm" },
|
||||
{ ".ots", ".xltx" },
|
||||
{ ".ott", ".docm" },
|
||||
{ ".ott", ".docx" },
|
||||
{ ".ott", ".dotm" },
|
||||
{ ".ott", ".dotx" },
|
||||
{ ".ott", ".epub" },
|
||||
{ ".ott", ".fb2" },
|
||||
{ ".ott", ".html" },
|
||||
{ ".ott", ".odt" },
|
||||
{ ".ott", ".pdf" },
|
||||
{ ".ott", ".rtf" },
|
||||
{ ".ott", ".txt" },
|
||||
{ ".oxps", ".pdf" },
|
||||
{ ".pot", ".odp" },
|
||||
{ ".pot", ".otp" },
|
||||
{ ".pot", ".pdf" },
|
||||
{ ".pot", ".potm" },
|
||||
{ ".pot", ".potx" },
|
||||
{ ".pot", ".pptm" },
|
||||
{ ".pot", ".pptx" },
|
||||
{ ".potm", ".odp" },
|
||||
{ ".potm", ".otp" },
|
||||
{ ".potm", ".pdf" },
|
||||
{ ".potm", ".potx" },
|
||||
{ ".potm", ".pptm" },
|
||||
{ ".potm", ".pptx" },
|
||||
{ ".potx", ".odp" },
|
||||
{ ".potx", ".otp" },
|
||||
{ ".potx", ".pdf" },
|
||||
{ ".potx", ".potm" },
|
||||
{ ".potx", ".pptm" },
|
||||
{ ".potx", ".pptx" },
|
||||
{ ".pps", ".odp" },
|
||||
{ ".pps", ".otp" },
|
||||
{ ".pps", ".pdf" },
|
||||
{ ".pps", ".potm" },
|
||||
{ ".pps", ".potx" },
|
||||
{ ".pps", ".pptm" },
|
||||
{ ".pps", ".pptx" },
|
||||
{ ".ppsm", ".odp" },
|
||||
{ ".ppsm", ".otp" },
|
||||
{ ".ppsm", ".pdf" },
|
||||
{ ".ppsm", ".potm" },
|
||||
{ ".ppsm", ".potx" },
|
||||
{ ".ppsm", ".pptm" },
|
||||
{ ".ppsm", ".pptx" },
|
||||
{ ".ppsx", ".odp" },
|
||||
{ ".ppsx", ".otp" },
|
||||
{ ".ppsx", ".pdf" },
|
||||
{ ".ppsx", ".potm" },
|
||||
{ ".ppsx", ".potx" },
|
||||
{ ".ppsx", ".pptm" },
|
||||
{ ".ppsx", ".pptx" },
|
||||
{ ".ppt", ".odp" },
|
||||
{ ".ppt", ".otp" },
|
||||
{ ".ppt", ".pdf" },
|
||||
{ ".ppt", ".potm" },
|
||||
{ ".ppt", ".potx" },
|
||||
{ ".ppt", ".pptm" },
|
||||
{ ".ppt", ".pptx" },
|
||||
{ ".pptm", ".odp" },
|
||||
{ ".pptm", ".otp" },
|
||||
{ ".pptm", ".pdf" },
|
||||
{ ".pptm", ".potm" },
|
||||
{ ".pptm", ".potx" },
|
||||
{ ".pptm", ".pptx" },
|
||||
{ ".pptt", ".pptx" },
|
||||
{ ".pptx", ".odp" },
|
||||
{ ".pptx", ".otp" },
|
||||
{ ".pptx", ".pdf" },
|
||||
{ ".pptx", ".potm" },
|
||||
{ ".pptx", ".potx" },
|
||||
{ ".pptx", ".pptm" },
|
||||
{ ".rtf", ".docm" },
|
||||
{ ".rtf", ".docx" },
|
||||
{ ".rtf", ".dotm" },
|
||||
{ ".rtf", ".dotx" },
|
||||
{ ".rtf", ".epub" },
|
||||
{ ".rtf", ".fb2" },
|
||||
{ ".rtf", ".html" },
|
||||
{ ".rtf", ".odt" },
|
||||
{ ".rtf", ".ott" },
|
||||
{ ".rtf", ".pdf" },
|
||||
{ ".rtf", ".txt" },
|
||||
{ ".txt", ".docm" },
|
||||
{ ".txt", ".docx" },
|
||||
{ ".txt", ".dotm" },
|
||||
{ ".txt", ".dotx" },
|
||||
{ ".txt", ".epub" },
|
||||
{ ".txt", ".fb2" },
|
||||
{ ".txt", ".html" },
|
||||
{ ".txt", ".odt" },
|
||||
{ ".txt", ".ott" },
|
||||
{ ".txt", ".pdf" },
|
||||
{ ".txt", ".rtf" },
|
||||
{ ".xls", ".csv" },
|
||||
{ ".xls", ".ods" },
|
||||
{ ".xls", ".ots" },
|
||||
{ ".xls", ".pdf" },
|
||||
{ ".xls", ".xlsm" },
|
||||
{ ".xls", ".xlsx" },
|
||||
{ ".xls", ".xltm" },
|
||||
{ ".xls", ".xltx" },
|
||||
{ ".xlsm", ".csv" },
|
||||
{ ".xlsm", ".ods" },
|
||||
{ ".xlsm", ".ots" },
|
||||
{ ".xlsm", ".pdf" },
|
||||
{ ".xlsm", ".xlsx" },
|
||||
{ ".xlsm", ".xltm" },
|
||||
{ ".xlsm", ".xltx" },
|
||||
{ ".xlst", ".xlsx" },
|
||||
{ ".xlsx", ".csv" },
|
||||
{ ".xlsx", ".ods" },
|
||||
{ ".xlsx", ".ots" },
|
||||
{ ".xlsx", ".pdf" },
|
||||
{ ".xlsx", ".xlsm" },
|
||||
{ ".xlsx", ".xltm" },
|
||||
{ ".xlsx", ".xltx" },
|
||||
{ ".xlt", ".csv" },
|
||||
{ ".xlt", ".ods" },
|
||||
{ ".xlt", ".ots" },
|
||||
{ ".xlt", ".pdf" },
|
||||
{ ".xlt", ".xlsm" },
|
||||
{ ".xlt", ".xlsx" },
|
||||
{ ".xlt", ".xltm" },
|
||||
{ ".xlt", ".xltx" },
|
||||
{ ".xltm", ".csv" },
|
||||
{ ".xltm", ".ods" },
|
||||
{ ".xltm", ".ots" },
|
||||
{ ".xltm", ".pdf" },
|
||||
{ ".xltm", ".xlsm" },
|
||||
{ ".xltm", ".xlsx" },
|
||||
{ ".xltm", ".xltx" },
|
||||
{ ".xltx", ".csv" },
|
||||
{ ".xltx", ".ods" },
|
||||
{ ".xltx", ".ots" },
|
||||
{ ".xltx", ".pdf" },
|
||||
{ ".xltx", ".xlsm" },
|
||||
{ ".xltx", ".xlsx" },
|
||||
{ ".xltx", ".xltm" },
|
||||
{ ".xml", ".docm" },
|
||||
{ ".xml", ".docx" },
|
||||
{ ".xml", ".dotm" },
|
||||
{ ".xml", ".dotx" },
|
||||
{ ".xml", ".epub" },
|
||||
{ ".xml", ".fb2" },
|
||||
{ ".xml", ".html" },
|
||||
{ ".xml", ".odt" },
|
||||
{ ".xml", ".ott" },
|
||||
{ ".xml", ".pdf" },
|
||||
{ ".xml", ".rtf" },
|
||||
{ ".xml", ".txt" },
|
||||
{ ".xps", ".pdf" }
|
||||
{
|
||||
{ ".csv", ".ods "},
|
||||
{ ".csv", ".ots "},
|
||||
{ ".csv", ".pdf "},
|
||||
{ ".csv", ".xlsm "},
|
||||
{ ".csv", ".xlsx "},
|
||||
{ ".csv", ".xltm "},
|
||||
{ ".csv", ".xltx "},
|
||||
{ ".doc", ".docm "},
|
||||
{ ".doc", ".docx "},
|
||||
{ ".doc", ".dotm "},
|
||||
{ ".doc", ".dotx "},
|
||||
{ ".doc", ".epub "},
|
||||
{ ".doc", ".fb2 "},
|
||||
{ ".doc", ".html "},
|
||||
{ ".doc", ".odt "},
|
||||
{ ".doc", ".ott "},
|
||||
{ ".doc", ".pdf "},
|
||||
{ ".doc", ".rtf "},
|
||||
{ ".doc", ".txt "},
|
||||
{ ".docm", ".docx "},
|
||||
{ ".docm", ".dotm "},
|
||||
{ ".docm", ".dotx "},
|
||||
{ ".docm", ".epub "},
|
||||
{ ".docm", ".fb2 "},
|
||||
{ ".docm", ".html "},
|
||||
{ ".docm", ".odt "},
|
||||
{ ".docm", ".ott "},
|
||||
{ ".docm", ".pdf "},
|
||||
{ ".docm", ".rtf "},
|
||||
{ ".docm", ".txt "},
|
||||
{ ".doct", ".docx "},
|
||||
{ ".docx", ".docm "},
|
||||
{ ".docx", ".docxf "},
|
||||
{ ".docx", ".dotm "},
|
||||
{ ".docx", ".dotx "},
|
||||
{ ".docx", ".epub "},
|
||||
{ ".docx", ".fb2 "},
|
||||
{ ".docx", ".html "},
|
||||
{ ".docx", ".odt "},
|
||||
{ ".docx", ".ott "},
|
||||
{ ".docx", ".pdf "},
|
||||
{ ".docx", ".rtf "},
|
||||
{ ".docx", ".txt "},
|
||||
{ ".docxf", ".docm "},
|
||||
{ ".docxf", ".docx "},
|
||||
{ ".docxf", ".dotm "},
|
||||
{ ".docxf", ".dotx "},
|
||||
{ ".docxf", ".epub "},
|
||||
{ ".docxf", ".fb2 "},
|
||||
{ ".docxf", ".html "},
|
||||
{ ".docxf", ".odt "},
|
||||
{ ".docxf", ".oform "},
|
||||
{ ".docxf", ".ott "},
|
||||
{ ".docxf", ".pdf "},
|
||||
{ ".docxf", ".rtf "},
|
||||
{ ".docxf", ".txt "},
|
||||
{ ".dot", ".docm "},
|
||||
{ ".dot", ".docx "},
|
||||
{ ".dot", ".dotm "},
|
||||
{ ".dot", ".dotx "},
|
||||
{ ".dot", ".epub "},
|
||||
{ ".dot", ".fb2 "},
|
||||
{ ".dot", ".html "},
|
||||
{ ".dot", ".odt "},
|
||||
{ ".dot", ".ott "},
|
||||
{ ".dot", ".pdf "},
|
||||
{ ".dot", ".rtf "},
|
||||
{ ".dot", ".txt "},
|
||||
{ ".dotm", ".docm "},
|
||||
{ ".dotm", ".docx "},
|
||||
{ ".dotm", ".dotx "},
|
||||
{ ".dotm", ".epub "},
|
||||
{ ".dotm", ".fb2 "},
|
||||
{ ".dotm", ".html "},
|
||||
{ ".dotm", ".odt "},
|
||||
{ ".dotm", ".ott "},
|
||||
{ ".dotm", ".pdf "},
|
||||
{ ".dotm", ".rtf "},
|
||||
{ ".dotm", ".txt "},
|
||||
{ ".dotx", ".docm "},
|
||||
{ ".dotx", ".docx "},
|
||||
{ ".dotx", ".dotm "},
|
||||
{ ".dotx", ".epub "},
|
||||
{ ".dotx", ".fb2 "},
|
||||
{ ".dotx", ".html "},
|
||||
{ ".dotx", ".odt "},
|
||||
{ ".dotx", ".ott "},
|
||||
{ ".dotx", ".pdf "},
|
||||
{ ".dotx", ".rtf "},
|
||||
{ ".dotx", ".txt "},
|
||||
{ ".epub", ".docm "},
|
||||
{ ".epub", ".docx "},
|
||||
{ ".epub", ".dotm "},
|
||||
{ ".epub", ".dotx "},
|
||||
{ ".epub", ".fb2 "},
|
||||
{ ".epub", ".html "},
|
||||
{ ".epub", ".odt "},
|
||||
{ ".epub", ".ott "},
|
||||
{ ".epub", ".pdf "},
|
||||
{ ".epub", ".rtf "},
|
||||
{ ".epub", ".txt "},
|
||||
{ ".fb2", ".docm "},
|
||||
{ ".fb2", ".docx "},
|
||||
{ ".fb2", ".dotm "},
|
||||
{ ".fb2", ".dotx "},
|
||||
{ ".fb2", ".epub "},
|
||||
{ ".fb2", ".html "},
|
||||
{ ".fb2", ".odt "},
|
||||
{ ".fb2", ".ott "},
|
||||
{ ".fb2", ".pdf "},
|
||||
{ ".fb2", ".rtf "},
|
||||
{ ".fb2", ".txt "},
|
||||
{ ".fodp", ".odp "},
|
||||
{ ".fodp", ".otp "},
|
||||
{ ".fodp", ".pdf "},
|
||||
{ ".fodp", ".potm "},
|
||||
{ ".fodp", ".potx "},
|
||||
{ ".fodp", ".ppsm "},
|
||||
{ ".fodp", ".ppsx "},
|
||||
{ ".fodp", ".pptm "},
|
||||
{ ".fodp", ".pptx "},
|
||||
{ ".fods", ".csv "},
|
||||
{ ".fods", ".ods "},
|
||||
{ ".fods", ".ots "},
|
||||
{ ".fods", ".pdf "},
|
||||
{ ".fods", ".xlsm "},
|
||||
{ ".fods", ".xlsx "},
|
||||
{ ".fods", ".xltm "},
|
||||
{ ".fods", ".xltx "},
|
||||
{ ".fodt", ".docm "},
|
||||
{ ".fodt", ".docx "},
|
||||
{ ".fodt", ".dotm "},
|
||||
{ ".fodt", ".dotx "},
|
||||
{ ".fodt", ".epub "},
|
||||
{ ".fodt", ".fb2 "},
|
||||
{ ".fodt", ".html "},
|
||||
{ ".fodt", ".odt "},
|
||||
{ ".fodt", ".ott "},
|
||||
{ ".fodt", ".pdf "},
|
||||
{ ".fodt", ".rtf "},
|
||||
{ ".fodt", ".txt "},
|
||||
{ ".html", ".docm "},
|
||||
{ ".html", ".docx "},
|
||||
{ ".html", ".dotm "},
|
||||
{ ".html", ".dotx "},
|
||||
{ ".html", ".epub "},
|
||||
{ ".html", ".fb2 "},
|
||||
{ ".html", ".odt "},
|
||||
{ ".html", ".ott "},
|
||||
{ ".html", ".pdf "},
|
||||
{ ".html", ".rtf "},
|
||||
{ ".html", ".txt "},
|
||||
{ ".mht", ".docm "},
|
||||
{ ".mht", ".docx "},
|
||||
{ ".mht", ".dotm "},
|
||||
{ ".mht", ".dotx "},
|
||||
{ ".mht", ".epub "},
|
||||
{ ".mht", ".fb2 "},
|
||||
{ ".mht", ".odt "},
|
||||
{ ".mht", ".ott "},
|
||||
{ ".mht", ".pdf "},
|
||||
{ ".mht", ".rtf "},
|
||||
{ ".mht", ".txt "},
|
||||
{ ".odp", ".otp "},
|
||||
{ ".odp", ".pdf "},
|
||||
{ ".odp", ".potm "},
|
||||
{ ".odp", ".potx "},
|
||||
{ ".odp", ".ppsm "},
|
||||
{ ".odp", ".ppsx "},
|
||||
{ ".odp", ".pptm "},
|
||||
{ ".odp", ".pptx "},
|
||||
{ ".ods", ".csv "},
|
||||
{ ".ods", ".ots "},
|
||||
{ ".ods", ".pdf "},
|
||||
{ ".ods", ".xlsm "},
|
||||
{ ".ods", ".xlsx "},
|
||||
{ ".ods", ".xltm "},
|
||||
{ ".ods", ".xltx "},
|
||||
{ ".odt", ".docm "},
|
||||
{ ".odt", ".docx "},
|
||||
{ ".odt", ".dotm "},
|
||||
{ ".odt", ".dotx "},
|
||||
{ ".odt", ".epub "},
|
||||
{ ".odt", ".fb2 "},
|
||||
{ ".odt", ".html "},
|
||||
{ ".odt", ".ott "},
|
||||
{ ".odt", ".pdf "},
|
||||
{ ".odt", ".rtf "},
|
||||
{ ".odt", ".txt "},
|
||||
{ ".otp", ".odp "},
|
||||
{ ".otp", ".pdf "},
|
||||
{ ".otp", ".potm "},
|
||||
{ ".otp", ".potx "},
|
||||
{ ".otp", ".ppsm "},
|
||||
{ ".otp", ".ppsx "},
|
||||
{ ".otp", ".pptm "},
|
||||
{ ".otp", ".pptx "},
|
||||
{ ".ots", ".csv "},
|
||||
{ ".ots", ".ods "},
|
||||
{ ".ots", ".pdf "},
|
||||
{ ".ots", ".xlsm "},
|
||||
{ ".ots", ".xlsx "},
|
||||
{ ".ots", ".xltm "},
|
||||
{ ".ots", ".xltx "},
|
||||
{ ".ott", ".docm "},
|
||||
{ ".ott", ".docx "},
|
||||
{ ".ott", ".dotm "},
|
||||
{ ".ott", ".dotx "},
|
||||
{ ".ott", ".epub "},
|
||||
{ ".ott", ".fb2 "},
|
||||
{ ".ott", ".html "},
|
||||
{ ".ott", ".odt "},
|
||||
{ ".ott", ".pdf "},
|
||||
{ ".ott", ".rtf "},
|
||||
{ ".ott", ".txt "},
|
||||
{ ".oxps", ".docm "},
|
||||
{ ".oxps", ".docx "},
|
||||
{ ".oxps", ".dotm "},
|
||||
{ ".oxps", ".dotx "},
|
||||
{ ".oxps", ".epub "},
|
||||
{ ".oxps", ".fb2 "},
|
||||
{ ".oxps", ".html "},
|
||||
{ ".oxps", ".odt "},
|
||||
{ ".oxps", ".ott "},
|
||||
{ ".oxps", ".pdf "},
|
||||
{ ".oxps", ".rtf "},
|
||||
{ ".oxps", ".txt "},
|
||||
{ ".pdf", ".docm "},
|
||||
{ ".pdf", ".docx "},
|
||||
{ ".pdf", ".dotm "},
|
||||
{ ".pdf", ".dotx "},
|
||||
{ ".pdf", ".epub "},
|
||||
{ ".pdf", ".fb2 "},
|
||||
{ ".pdf", ".html "},
|
||||
{ ".pdf", ".odt "},
|
||||
{ ".pdf", ".ott "},
|
||||
{ ".pdf", ".rtf "},
|
||||
{ ".pdf", ".txt "},
|
||||
{ ".pot", ".odp "},
|
||||
{ ".pot", ".otp "},
|
||||
{ ".pot", ".pdf "},
|
||||
{ ".pot", ".potm "},
|
||||
{ ".pot", ".potx "},
|
||||
{ ".pot", ".ppsm "},
|
||||
{ ".pot", ".ppsx "},
|
||||
{ ".pot", ".pptm "},
|
||||
{ ".pot", ".pptx "},
|
||||
{ ".potm", ".odp "},
|
||||
{ ".potm", ".otp "},
|
||||
{ ".potm", ".pdf "},
|
||||
{ ".potm", ".potx "},
|
||||
{ ".potm", ".ppsm "},
|
||||
{ ".potm", ".ppsx "},
|
||||
{ ".potm", ".pptm "},
|
||||
{ ".potm", ".pptx "},
|
||||
{ ".potx", ".odp "},
|
||||
{ ".potx", ".otp "},
|
||||
{ ".potx", ".pdf "},
|
||||
{ ".potx", ".potm "},
|
||||
{ ".potx", ".ppsm "},
|
||||
{ ".potx", ".ppsx "},
|
||||
{ ".potx", ".pptm "},
|
||||
{ ".potx", ".pptx "},
|
||||
{ ".pps", ".odp "},
|
||||
{ ".pps", ".otp "},
|
||||
{ ".pps", ".pdf "},
|
||||
{ ".pps", ".potm "},
|
||||
{ ".pps", ".potx "},
|
||||
{ ".pps", ".ppsm "},
|
||||
{ ".pps", ".ppsx "},
|
||||
{ ".pps", ".pptm "},
|
||||
{ ".pps", ".pptx "},
|
||||
{ ".ppsm", ".odp "},
|
||||
{ ".ppsm", ".otp "},
|
||||
{ ".ppsm", ".pdf "},
|
||||
{ ".ppsm", ".potm "},
|
||||
{ ".ppsm", ".potx "},
|
||||
{ ".ppsm", ".ppsx "},
|
||||
{ ".ppsm", ".pptm "},
|
||||
{ ".ppsm", ".pptx "},
|
||||
{ ".ppsx", ".odp "},
|
||||
{ ".ppsx", ".otp "},
|
||||
{ ".ppsx", ".pdf "},
|
||||
{ ".ppsx", ".potm "},
|
||||
{ ".ppsx", ".potx "},
|
||||
{ ".ppsx", ".ppsm "},
|
||||
{ ".ppsx", ".pptm "},
|
||||
{ ".ppsx", ".pptx "},
|
||||
{ ".ppt", ".odp "},
|
||||
{ ".ppt", ".otp "},
|
||||
{ ".ppt", ".pdf "},
|
||||
{ ".ppt", ".potm "},
|
||||
{ ".ppt", ".potx "},
|
||||
{ ".ppt", ".ppsm "},
|
||||
{ ".ppt", ".ppsx "},
|
||||
{ ".ppt", ".pptm "},
|
||||
{ ".ppt", ".pptx "},
|
||||
{ ".pptm", ".odp "},
|
||||
{ ".pptm", ".otp "},
|
||||
{ ".pptm", ".pdf "},
|
||||
{ ".pptm", ".potm "},
|
||||
{ ".pptm", ".potx "},
|
||||
{ ".pptm", ".ppsm "},
|
||||
{ ".pptm", ".ppsx "},
|
||||
{ ".pptm", ".pptx "},
|
||||
{ ".pptt", ".pptx "},
|
||||
{ ".pptx", ".odp "},
|
||||
{ ".pptx", ".otp "},
|
||||
{ ".pptx", ".pdf "},
|
||||
{ ".pptx", ".potm "},
|
||||
{ ".pptx", ".potx "},
|
||||
{ ".pptx", ".ppsm "},
|
||||
{ ".pptx", ".ppsx "},
|
||||
{ ".pptx", ".pptm "},
|
||||
{ ".rtf", ".docm "},
|
||||
{ ".rtf", ".docx "},
|
||||
{ ".rtf", ".dotm "},
|
||||
{ ".rtf", ".dotx "},
|
||||
{ ".rtf", ".epub "},
|
||||
{ ".rtf", ".fb2 "},
|
||||
{ ".rtf", ".html "},
|
||||
{ ".rtf", ".odt "},
|
||||
{ ".rtf", ".ott "},
|
||||
{ ".rtf", ".pdf "},
|
||||
{ ".rtf", ".txt "},
|
||||
{ ".txt", ".docm "},
|
||||
{ ".txt", ".docx "},
|
||||
{ ".txt", ".dotm "},
|
||||
{ ".txt", ".dotx "},
|
||||
{ ".txt", ".epub "},
|
||||
{ ".txt", ".fb2 "},
|
||||
{ ".txt", ".html "},
|
||||
{ ".txt", ".odt "},
|
||||
{ ".txt", ".ott "},
|
||||
{ ".txt", ".pdf "},
|
||||
{ ".txt", ".rtf "},
|
||||
{ ".xls", ".csv "},
|
||||
{ ".xls", ".ods "},
|
||||
{ ".xls", ".ots "},
|
||||
{ ".xls", ".pdf "},
|
||||
{ ".xls", ".xlsm "},
|
||||
{ ".xls", ".xlsx "},
|
||||
{ ".xls", ".xltm "},
|
||||
{ ".xls", ".xltx "},
|
||||
{ ".xlsm", ".csv "},
|
||||
{ ".xlsm", ".ods "},
|
||||
{ ".xlsm", ".ots "},
|
||||
{ ".xlsm", ".pdf "},
|
||||
{ ".xlsm", ".xlsx "},
|
||||
{ ".xlsm", ".xltm "},
|
||||
{ ".xlsm", ".xltx "},
|
||||
{ ".xlst", ".xlsx "},
|
||||
{ ".xlsx", ".csv "},
|
||||
{ ".xlsx", ".ods "},
|
||||
{ ".xlsx", ".ots "},
|
||||
{ ".xlsx", ".pdf "},
|
||||
{ ".xlsx", ".xlsm "},
|
||||
{ ".xlsx", ".xltm "},
|
||||
{ ".xlsx", ".xltx "},
|
||||
{ ".xlt", ".csv "},
|
||||
{ ".xlt", ".ods "},
|
||||
{ ".xlt", ".ots "},
|
||||
{ ".xlt", ".pdf "},
|
||||
{ ".xlt", ".xlsm "},
|
||||
{ ".xlt", ".xlsx "},
|
||||
{ ".xlt", ".xltm "},
|
||||
{ ".xlt", ".xltx "},
|
||||
{ ".xltm", ".csv "},
|
||||
{ ".xltm", ".ods "},
|
||||
{ ".xltm", ".ots "},
|
||||
{ ".xltm", ".pdf "},
|
||||
{ ".xltm", ".xlsm "},
|
||||
{ ".xltm", ".xlsx "},
|
||||
{ ".xltm", ".xltx "},
|
||||
{ ".xltx", ".csv "},
|
||||
{ ".xltx", ".ods "},
|
||||
{ ".xltx", ".ots "},
|
||||
{ ".xltx", ".pdf "},
|
||||
{ ".xltx", ".xlsm "},
|
||||
{ ".xltx", ".xlsx "},
|
||||
{ ".xltx", ".xltm "},
|
||||
{ ".xml", ".docm "},
|
||||
{ ".xml", ".docx "},
|
||||
{ ".xml", ".dotm "},
|
||||
{ ".xml", ".dotx "},
|
||||
{ ".xml", ".epub "},
|
||||
{ ".xml", ".fb2 "},
|
||||
{ ".xml", ".html "},
|
||||
{ ".xml", ".odt "},
|
||||
{ ".xml", ".ott "},
|
||||
{ ".xml", ".pdf "},
|
||||
{ ".xml", ".rtf "},
|
||||
{ ".xml", ".txt "},
|
||||
{ ".xps", ".docm "},
|
||||
{ ".xps", ".docx "},
|
||||
{ ".xps", ".dotm "},
|
||||
{ ".xps", ".dotx "},
|
||||
{ ".xps", ".epub "},
|
||||
{ ".xps", ".fb2 "},
|
||||
{ ".xps", ".html "},
|
||||
{ ".xps", ".odt "},
|
||||
{ ".xps", ".ott "},
|
||||
{ ".xps", ".pdf "},
|
||||
{ ".xps", ".rtf "},
|
||||
{ ".xps", ".txt" }
|
||||
});
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -68,7 +68,7 @@ namespace ASC.Migrations.PostgreSql.Migrations.CoreDb
|
||||
new
|
||||
{
|
||||
Tenant = -1,
|
||||
Features = "trial,audit,ldap,sso,whitelabel,thirdparty,restore,total_size:107374182400,file_size:100,manager:1",
|
||||
Features = "trial,audit,ldap,sso,whitelabel,thirdparty,restore,oauth,total_size:107374182400,file_size:100,manager:1",
|
||||
Name = "trial",
|
||||
Price = 0m,
|
||||
Visible = false
|
||||
@ -76,7 +76,7 @@ namespace ASC.Migrations.PostgreSql.Migrations.CoreDb
|
||||
new
|
||||
{
|
||||
Tenant = -2,
|
||||
Features = "audit,ldap,sso,whitelabel,thirdparty,restore,contentsearch,total_size:107374182400,file_size:1024,manager:1",
|
||||
Features = "audit,ldap,sso,whitelabel,thirdparty,restore,oauth,contentsearch,total_size:107374182400,file_size:1024,manager:1",
|
||||
Name = "admin",
|
||||
Price = 30m,
|
||||
ProductId = "1002",
|
||||
@ -85,7 +85,7 @@ namespace ASC.Migrations.PostgreSql.Migrations.CoreDb
|
||||
new
|
||||
{
|
||||
Tenant = -3,
|
||||
Features = "free,total_size:2147483648,manager:5,room:5",
|
||||
Features = "free,total_size:2147483648,manager:3,room:12",
|
||||
Name = "startup",
|
||||
Price = 0m,
|
||||
Visible = false
|
||||
|
@ -113,19 +113,19 @@ public partial class CoreDbContextMigrate : Migration
|
||||
schema: "onlyoffice",
|
||||
table: "tenants_quota",
|
||||
columns: new[] { "tenant", "description", "features", "name", "visible" },
|
||||
values: new object[] { -3, null, "free,total_size:2147483648,manager:5,room:5", "startup", false });
|
||||
values: new object[] { -3, null, "free,total_size:2147483648,manager:3,room:12", "startup", false });
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
schema: "onlyoffice",
|
||||
table: "tenants_quota",
|
||||
columns: new[] { "tenant", "description", "features", "name", "price", "product_id", "visible" },
|
||||
values: new object[] { -2, null, "audit,ldap,sso,whitelabel,thirdparty,restore,contentsearch,total_size:107374182400,file_size:1024,manager:1", "admin", 30m, "1002", true });
|
||||
values: new object[] { -2, null, "audit,ldap,sso,whitelabel,thirdparty,restore,oauth,contentsearch,total_size:107374182400,file_size:1024,manager:1", "admin", 30m, "1002", true });
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
schema: "onlyoffice",
|
||||
table: "tenants_quota",
|
||||
columns: new[] { "tenant", "description", "features", "name", "visible" },
|
||||
values: new object[] { -1, null, "trial,audit,ldap,sso,whitelabel,thirdparty,restore,total_size:107374182400,file_size:100,manager:1", "trial", false });
|
||||
values: new object[] { -1, null, "trial,audit,ldap,sso,whitelabel,thirdparty,restore,oauth,total_size:107374182400,file_size:100,manager:1", "trial", false });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "last_modified_tenants_quotarow",
|
||||
|
@ -82,7 +82,7 @@ namespace ASC.Migrations.PostgreSql.Migrations.CoreDb
|
||||
new
|
||||
{
|
||||
Tenant = -3,
|
||||
Features = "free,total_size:2147483648,manager:5,room:5",
|
||||
Features = "free,total_size:2147483648,manager:3,room:12",
|
||||
Name = "startup",
|
||||
Price = 0m,
|
||||
Visible = false
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -318,354 +318,411 @@ public partial class FilesDbContextMigrate : Migration
|
||||
columns: new[] { "input", "output" },
|
||||
values: new object[,]
|
||||
{
|
||||
{ ".csv", ".ods" },
|
||||
{ ".csv", ".ots" },
|
||||
{ ".csv", ".pdf" },
|
||||
{ ".csv", ".xlsm" },
|
||||
{ ".csv", ".xlsx" },
|
||||
{ ".csv", ".xltm" },
|
||||
{ ".csv", ".xltx" },
|
||||
{ ".doc", ".docm" },
|
||||
{ ".doc", ".docx" },
|
||||
{ ".doc", ".dotm" },
|
||||
{ ".doc", ".dotx" },
|
||||
{ ".doc", ".epub" },
|
||||
{ ".doc", ".fb2" },
|
||||
{ ".doc", ".html" },
|
||||
{ ".doc", ".odt" },
|
||||
{ ".doc", ".ott" },
|
||||
{ ".doc", ".pdf" },
|
||||
{ ".doc", ".rtf" },
|
||||
{ ".doc", ".txt" },
|
||||
{ ".docm", ".docx" },
|
||||
{ ".docm", ".dotm" },
|
||||
{ ".docm", ".dotx" },
|
||||
{ ".docm", ".epub" },
|
||||
{ ".docm", ".fb2" },
|
||||
{ ".docm", ".html" },
|
||||
{ ".docm", ".odt" },
|
||||
{ ".docm", ".ott" },
|
||||
{ ".docm", ".pdf" },
|
||||
{ ".docm", ".rtf" },
|
||||
{ ".docm", ".txt" },
|
||||
{ ".doct", ".docx" },
|
||||
{ ".docx", ".docm" },
|
||||
{ ".docx", ".docxf" },
|
||||
{ ".docx", ".dotm" },
|
||||
{ ".docx", ".dotx" },
|
||||
{ ".docx", ".epub" },
|
||||
{ ".docx", ".fb2" },
|
||||
{ ".docx", ".html" },
|
||||
{ ".docx", ".odt" },
|
||||
{ ".docx", ".ott" },
|
||||
{ ".docx", ".pdf" },
|
||||
{ ".docx", ".rtf" },
|
||||
{ ".docx", ".txt" },
|
||||
{ ".docxf", ".docx" },
|
||||
{ ".docxf", ".dotx" },
|
||||
{ ".docxf", ".epub" },
|
||||
{ ".docxf", ".fb2" },
|
||||
{ ".docxf", ".html" },
|
||||
{ ".docxf", ".odt" },
|
||||
{ ".docxf", ".oform" },
|
||||
{ ".docxf", ".ott" },
|
||||
{ ".docxf", ".pdf" },
|
||||
{ ".docxf", ".rtf" },
|
||||
{ ".docxf", ".txt" },
|
||||
{ ".dot", ".docm" },
|
||||
{ ".dot", ".docx" },
|
||||
{ ".dot", ".dotm" },
|
||||
{ ".dot", ".dotx" },
|
||||
{ ".dot", ".epub" },
|
||||
{ ".dot", ".fb2" },
|
||||
{ ".dot", ".html" },
|
||||
{ ".dot", ".odt" },
|
||||
{ ".dot", ".ott" },
|
||||
{ ".dot", ".pdf" },
|
||||
{ ".dot", ".rtf" },
|
||||
{ ".dot", ".txt" },
|
||||
{ ".dotm", ".docm" },
|
||||
{ ".dotm", ".docx" },
|
||||
{ ".dotm", ".dotx" },
|
||||
{ ".dotm", ".epub" },
|
||||
{ ".dotm", ".fb2" },
|
||||
{ ".dotm", ".html" },
|
||||
{ ".dotm", ".odt" },
|
||||
{ ".dotm", ".ott" },
|
||||
{ ".dotm", ".pdf" },
|
||||
{ ".dotm", ".rtf" },
|
||||
{ ".dotm", ".txt" },
|
||||
{ ".dotx", ".docm" },
|
||||
{ ".dotx", ".docx" },
|
||||
{ ".dotx", ".dotm" },
|
||||
{ ".dotx", ".epub" },
|
||||
{ ".dotx", ".fb2" },
|
||||
{ ".dotx", ".html" },
|
||||
{ ".dotx", ".odt" },
|
||||
{ ".dotx", ".ott" },
|
||||
{ ".dotx", ".pdf" },
|
||||
{ ".dotx", ".rtf" },
|
||||
{ ".dotx", ".txt" },
|
||||
{ ".epub", ".docm" },
|
||||
{ ".epub", ".docx" },
|
||||
{ ".epub", ".dotm" },
|
||||
{ ".epub", ".dotx" },
|
||||
{ ".epub", ".fb2" },
|
||||
{ ".epub", ".html" },
|
||||
{ ".epub", ".odt" },
|
||||
{ ".epub", ".ott" },
|
||||
{ ".epub", ".pdf" },
|
||||
{ ".epub", ".rtf" },
|
||||
{ ".epub", ".txt" },
|
||||
{ ".fb2", ".docm" },
|
||||
{ ".fb2", ".docx" },
|
||||
{ ".fb2", ".dotm" },
|
||||
{ ".fb2", ".dotx" },
|
||||
{ ".fb2", ".epub" },
|
||||
{ ".fb2", ".html" },
|
||||
{ ".fb2", ".odt" },
|
||||
{ ".fb2", ".ott" },
|
||||
{ ".fb2", ".pdf" },
|
||||
{ ".fb2", ".rtf" },
|
||||
{ ".fb2", ".txt" },
|
||||
{ ".fodp", ".odp" },
|
||||
{ ".fodp", ".otp" },
|
||||
{ ".fodp", ".pdf" },
|
||||
{ ".fodp", ".potm" },
|
||||
{ ".fodp", ".potx" },
|
||||
{ ".fodp", ".pptm" },
|
||||
{ ".fodp", ".pptx" },
|
||||
{ ".fods", ".csv" },
|
||||
{ ".fods", ".ods" },
|
||||
{ ".fods", ".ots" },
|
||||
{ ".fods", ".pdf" },
|
||||
{ ".fods", ".xlsm" },
|
||||
{ ".fods", ".xlsx" },
|
||||
{ ".fods", ".xltm" },
|
||||
{ ".fods", ".xltx" },
|
||||
{ ".fodt", ".docm" },
|
||||
{ ".fodt", ".docx" },
|
||||
{ ".fodt", ".dotm" },
|
||||
{ ".fodt", ".dotx" },
|
||||
{ ".fodt", ".epub" },
|
||||
{ ".fodt", ".fb2" },
|
||||
{ ".fodt", ".html" },
|
||||
{ ".fodt", ".odt" },
|
||||
{ ".fodt", ".ott" },
|
||||
{ ".fodt", ".pdf" },
|
||||
{ ".fodt", ".rtf" },
|
||||
{ ".fodt", ".txt" },
|
||||
{ ".html", ".docm" },
|
||||
{ ".html", ".docx" },
|
||||
{ ".html", ".dotm" },
|
||||
{ ".html", ".dotx" },
|
||||
{ ".html", ".epub" },
|
||||
{ ".html", ".fb2" },
|
||||
{ ".html", ".odt" },
|
||||
{ ".html", ".ott" },
|
||||
{ ".html", ".pdf" },
|
||||
{ ".html", ".rtf" },
|
||||
{ ".html", ".txt" },
|
||||
{ ".mht", ".docm" },
|
||||
{ ".mht", ".docx" },
|
||||
{ ".mht", ".dotm" },
|
||||
{ ".mht", ".dotx" },
|
||||
{ ".mht", ".epub" },
|
||||
{ ".mht", ".fb2" },
|
||||
{ ".mht", ".odt" },
|
||||
{ ".mht", ".ott" },
|
||||
{ ".mht", ".pdf" },
|
||||
{ ".mht", ".rtf" },
|
||||
{ ".mht", ".txt" },
|
||||
{ ".odp", ".otp" },
|
||||
{ ".odp", ".pdf" },
|
||||
{ ".odp", ".potm" },
|
||||
{ ".odp", ".potx" },
|
||||
{ ".odp", ".pptm" },
|
||||
{ ".odp", ".pptx" },
|
||||
{ ".ods", ".csv" },
|
||||
{ ".ods", ".ots" },
|
||||
{ ".ods", ".pdf" },
|
||||
{ ".ods", ".xlsm" },
|
||||
{ ".ods", ".xlsx" },
|
||||
{ ".ods", ".xltm" },
|
||||
{ ".ods", ".xltx" },
|
||||
{ ".odt", ".docm" },
|
||||
{ ".odt", ".docx" },
|
||||
{ ".odt", ".dotm" },
|
||||
{ ".odt", ".dotx" },
|
||||
{ ".odt", ".epub" },
|
||||
{ ".odt", ".fb2" },
|
||||
{ ".odt", ".html" },
|
||||
{ ".odt", ".ott" },
|
||||
{ ".odt", ".pdf" },
|
||||
{ ".odt", ".rtf" },
|
||||
{ ".odt", ".txt" },
|
||||
{ ".otp", ".odp" },
|
||||
{ ".otp", ".pdf" },
|
||||
{ ".otp", ".potm" },
|
||||
{ ".otp", ".potx" },
|
||||
{ ".otp", ".pptm" },
|
||||
{ ".otp", ".pptx" },
|
||||
{ ".ots", ".csv" },
|
||||
{ ".ots", ".ods" },
|
||||
{ ".ots", ".pdf" },
|
||||
{ ".ots", ".xlsm" },
|
||||
{ ".ots", ".xlsx" },
|
||||
{ ".ots", ".xltm" },
|
||||
{ ".ots", ".xltx" },
|
||||
{ ".ott", ".docm" },
|
||||
{ ".ott", ".docx" },
|
||||
{ ".ott", ".dotm" },
|
||||
{ ".ott", ".dotx" },
|
||||
{ ".ott", ".epub" },
|
||||
{ ".ott", ".fb2" },
|
||||
{ ".ott", ".html" },
|
||||
{ ".ott", ".odt" },
|
||||
{ ".ott", ".pdf" },
|
||||
{ ".ott", ".rtf" },
|
||||
{ ".ott", ".txt" },
|
||||
{ ".oxps", ".pdf" },
|
||||
{ ".pot", ".odp" },
|
||||
{ ".pot", ".otp" },
|
||||
{ ".pot", ".pdf" },
|
||||
{ ".pot", ".potm" },
|
||||
{ ".pot", ".potx" },
|
||||
{ ".pot", ".pptm" },
|
||||
{ ".pot", ".pptx" },
|
||||
{ ".potm", ".odp" },
|
||||
{ ".potm", ".otp" },
|
||||
{ ".potm", ".pdf" },
|
||||
{ ".potm", ".potx" },
|
||||
{ ".potm", ".pptm" },
|
||||
{ ".potm", ".pptx" },
|
||||
{ ".potx", ".odp" },
|
||||
{ ".potx", ".otp" },
|
||||
{ ".potx", ".pdf" },
|
||||
{ ".potx", ".potm" },
|
||||
{ ".potx", ".pptm" },
|
||||
{ ".potx", ".pptx" },
|
||||
{ ".pps", ".odp" },
|
||||
{ ".pps", ".otp" },
|
||||
{ ".pps", ".pdf" },
|
||||
{ ".pps", ".potm" },
|
||||
{ ".pps", ".potx" },
|
||||
{ ".pps", ".pptm" },
|
||||
{ ".pps", ".pptx" },
|
||||
{ ".ppsm", ".odp" },
|
||||
{ ".ppsm", ".otp" },
|
||||
{ ".ppsm", ".pdf" },
|
||||
{ ".ppsm", ".potm" },
|
||||
{ ".ppsm", ".potx" },
|
||||
{ ".ppsm", ".pptm" },
|
||||
{ ".ppsm", ".pptx" },
|
||||
{ ".ppsx", ".odp" },
|
||||
{ ".ppsx", ".otp" },
|
||||
{ ".ppsx", ".pdf" },
|
||||
{ ".ppsx", ".potm" },
|
||||
{ ".ppsx", ".potx" },
|
||||
{ ".ppsx", ".pptm" },
|
||||
{ ".ppsx", ".pptx" },
|
||||
{ ".ppt", ".odp" },
|
||||
{ ".ppt", ".otp" },
|
||||
{ ".ppt", ".pdf" },
|
||||
{ ".ppt", ".potm" },
|
||||
{ ".ppt", ".potx" },
|
||||
{ ".ppt", ".pptm" },
|
||||
{ ".ppt", ".pptx" },
|
||||
{ ".pptm", ".odp" },
|
||||
{ ".pptm", ".otp" },
|
||||
{ ".pptm", ".pdf" },
|
||||
{ ".pptm", ".potm" },
|
||||
{ ".pptm", ".potx" },
|
||||
{ ".pptm", ".pptx" },
|
||||
{ ".pptt", ".pptx" },
|
||||
{ ".pptx", ".odp" },
|
||||
{ ".pptx", ".otp" },
|
||||
{ ".pptx", ".pdf" },
|
||||
{ ".pptx", ".potm" },
|
||||
{ ".pptx", ".potx" },
|
||||
{ ".pptx", ".pptm" },
|
||||
{ ".rtf", ".docm" },
|
||||
{ ".rtf", ".docx" },
|
||||
{ ".rtf", ".dotm" },
|
||||
{ ".rtf", ".dotx" },
|
||||
{ ".rtf", ".epub" },
|
||||
{ ".rtf", ".fb2" },
|
||||
{ ".rtf", ".html" },
|
||||
{ ".rtf", ".odt" },
|
||||
{ ".rtf", ".ott" },
|
||||
{ ".rtf", ".pdf" },
|
||||
{ ".rtf", ".txt" },
|
||||
{ ".txt", ".docm" },
|
||||
{ ".txt", ".docx" },
|
||||
{ ".txt", ".dotm" },
|
||||
{ ".txt", ".dotx" },
|
||||
{ ".txt", ".epub" },
|
||||
{ ".txt", ".fb2" },
|
||||
{ ".txt", ".html" },
|
||||
{ ".txt", ".odt" },
|
||||
{ ".txt", ".ott" },
|
||||
{ ".txt", ".pdf" },
|
||||
{ ".txt", ".rtf" },
|
||||
{ ".xls", ".csv" },
|
||||
{ ".xls", ".ods" },
|
||||
{ ".xls", ".ots" },
|
||||
{ ".xls", ".pdf" },
|
||||
{ ".xls", ".xlsm" },
|
||||
{ ".xls", ".xlsx" },
|
||||
{ ".xls", ".xltm" },
|
||||
{ ".xls", ".xltx" },
|
||||
{ ".xlsm", ".csv" },
|
||||
{ ".xlsm", ".ods" },
|
||||
{ ".xlsm", ".ots" },
|
||||
{ ".xlsm", ".pdf" },
|
||||
{ ".xlsm", ".xlsx" },
|
||||
{ ".xlsm", ".xltm" },
|
||||
{ ".xlsm", ".xltx" },
|
||||
{ ".xlst", ".xlsx" },
|
||||
{ ".xlsx", ".csv" },
|
||||
{ ".xlsx", ".ods" },
|
||||
{ ".xlsx", ".ots" },
|
||||
{ ".xlsx", ".pdf" },
|
||||
{ ".xlsx", ".xlsm" },
|
||||
{ ".xlsx", ".xltm" },
|
||||
{ ".xlsx", ".xltx" },
|
||||
{ ".xlt", ".csv" },
|
||||
{ ".xlt", ".ods" },
|
||||
{ ".xlt", ".ots" },
|
||||
{ ".xlt", ".pdf" },
|
||||
{ ".xlt", ".xlsm" },
|
||||
{ ".xlt", ".xlsx" },
|
||||
{ ".xlt", ".xltm" },
|
||||
{ ".xlt", ".xltx" },
|
||||
{ ".xltm", ".csv" },
|
||||
{ ".xltm", ".ods" },
|
||||
{ ".xltm", ".ots" },
|
||||
{ ".xltm", ".pdf" },
|
||||
{ ".xltm", ".xlsm" },
|
||||
{ ".xltm", ".xlsx" },
|
||||
{ ".xltm", ".xltx" },
|
||||
{ ".xltx", ".csv" },
|
||||
{ ".xltx", ".ods" },
|
||||
{ ".xltx", ".ots" },
|
||||
{ ".xltx", ".pdf" },
|
||||
{ ".xltx", ".xlsm" },
|
||||
{ ".xltx", ".xlsx" },
|
||||
{ ".xltx", ".xltm" },
|
||||
{ ".xml", ".docm" },
|
||||
{ ".xml", ".docx" },
|
||||
{ ".xml", ".dotm" },
|
||||
{ ".xml", ".dotx" },
|
||||
{ ".xml", ".epub" },
|
||||
{ ".xml", ".fb2" },
|
||||
{ ".xml", ".html" },
|
||||
{ ".xml", ".odt" },
|
||||
{ ".xml", ".ott" },
|
||||
{ ".xml", ".pdf" },
|
||||
{ ".xml", ".rtf" },
|
||||
{ ".xml", ".txt" },
|
||||
{ ".xps", ".pdf" }
|
||||
{ ".csv", ".ods "},
|
||||
{ ".csv", ".ots "},
|
||||
{ ".csv", ".pdf "},
|
||||
{ ".csv", ".xlsm "},
|
||||
{ ".csv", ".xlsx "},
|
||||
{ ".csv", ".xltm "},
|
||||
{ ".csv", ".xltx "},
|
||||
{ ".doc", ".docm "},
|
||||
{ ".doc", ".docx "},
|
||||
{ ".doc", ".dotm "},
|
||||
{ ".doc", ".dotx "},
|
||||
{ ".doc", ".epub "},
|
||||
{ ".doc", ".fb2 "},
|
||||
{ ".doc", ".html "},
|
||||
{ ".doc", ".odt "},
|
||||
{ ".doc", ".ott "},
|
||||
{ ".doc", ".pdf "},
|
||||
{ ".doc", ".rtf "},
|
||||
{ ".doc", ".txt "},
|
||||
{ ".docm", ".docx "},
|
||||
{ ".docm", ".dotm "},
|
||||
{ ".docm", ".dotx "},
|
||||
{ ".docm", ".epub "},
|
||||
{ ".docm", ".fb2 "},
|
||||
{ ".docm", ".html "},
|
||||
{ ".docm", ".odt "},
|
||||
{ ".docm", ".ott "},
|
||||
{ ".docm", ".pdf "},
|
||||
{ ".docm", ".rtf "},
|
||||
{ ".docm", ".txt "},
|
||||
{ ".doct", ".docx "},
|
||||
{ ".docx", ".docm "},
|
||||
{ ".docx", ".docxf "},
|
||||
{ ".docx", ".dotm "},
|
||||
{ ".docx", ".dotx "},
|
||||
{ ".docx", ".epub "},
|
||||
{ ".docx", ".fb2 "},
|
||||
{ ".docx", ".html "},
|
||||
{ ".docx", ".odt "},
|
||||
{ ".docx", ".ott "},
|
||||
{ ".docx", ".pdf "},
|
||||
{ ".docx", ".rtf "},
|
||||
{ ".docx", ".txt "},
|
||||
{ ".docxf", ".docm "},
|
||||
{ ".docxf", ".docx "},
|
||||
{ ".docxf", ".dotm "},
|
||||
{ ".docxf", ".dotx "},
|
||||
{ ".docxf", ".epub "},
|
||||
{ ".docxf", ".fb2 "},
|
||||
{ ".docxf", ".html "},
|
||||
{ ".docxf", ".odt "},
|
||||
{ ".docxf", ".oform "},
|
||||
{ ".docxf", ".ott "},
|
||||
{ ".docxf", ".pdf "},
|
||||
{ ".docxf", ".rtf "},
|
||||
{ ".docxf", ".txt "},
|
||||
{ ".dot", ".docm "},
|
||||
{ ".dot", ".docx "},
|
||||
{ ".dot", ".dotm "},
|
||||
{ ".dot", ".dotx "},
|
||||
{ ".dot", ".epub "},
|
||||
{ ".dot", ".fb2 "},
|
||||
{ ".dot", ".html "},
|
||||
{ ".dot", ".odt "},
|
||||
{ ".dot", ".ott "},
|
||||
{ ".dot", ".pdf "},
|
||||
{ ".dot", ".rtf "},
|
||||
{ ".dot", ".txt "},
|
||||
{ ".dotm", ".docm "},
|
||||
{ ".dotm", ".docx "},
|
||||
{ ".dotm", ".dotx "},
|
||||
{ ".dotm", ".epub "},
|
||||
{ ".dotm", ".fb2 "},
|
||||
{ ".dotm", ".html "},
|
||||
{ ".dotm", ".odt "},
|
||||
{ ".dotm", ".ott "},
|
||||
{ ".dotm", ".pdf "},
|
||||
{ ".dotm", ".rtf "},
|
||||
{ ".dotm", ".txt "},
|
||||
{ ".dotx", ".docm "},
|
||||
{ ".dotx", ".docx "},
|
||||
{ ".dotx", ".dotm "},
|
||||
{ ".dotx", ".epub "},
|
||||
{ ".dotx", ".fb2 "},
|
||||
{ ".dotx", ".html "},
|
||||
{ ".dotx", ".odt "},
|
||||
{ ".dotx", ".ott "},
|
||||
{ ".dotx", ".pdf "},
|
||||
{ ".dotx", ".rtf "},
|
||||
{ ".dotx", ".txt "},
|
||||
{ ".epub", ".docm "},
|
||||
{ ".epub", ".docx "},
|
||||
{ ".epub", ".dotm "},
|
||||
{ ".epub", ".dotx "},
|
||||
{ ".epub", ".fb2 "},
|
||||
{ ".epub", ".html "},
|
||||
{ ".epub", ".odt "},
|
||||
{ ".epub", ".ott "},
|
||||
{ ".epub", ".pdf "},
|
||||
{ ".epub", ".rtf "},
|
||||
{ ".epub", ".txt "},
|
||||
{ ".fb2", ".docm "},
|
||||
{ ".fb2", ".docx "},
|
||||
{ ".fb2", ".dotm "},
|
||||
{ ".fb2", ".dotx "},
|
||||
{ ".fb2", ".epub "},
|
||||
{ ".fb2", ".html "},
|
||||
{ ".fb2", ".odt "},
|
||||
{ ".fb2", ".ott "},
|
||||
{ ".fb2", ".pdf "},
|
||||
{ ".fb2", ".rtf "},
|
||||
{ ".fb2", ".txt "},
|
||||
{ ".fodp", ".odp "},
|
||||
{ ".fodp", ".otp "},
|
||||
{ ".fodp", ".pdf "},
|
||||
{ ".fodp", ".potm "},
|
||||
{ ".fodp", ".potx "},
|
||||
{ ".fodp", ".ppsm "},
|
||||
{ ".fodp", ".ppsx "},
|
||||
{ ".fodp", ".pptm "},
|
||||
{ ".fodp", ".pptx "},
|
||||
{ ".fods", ".csv "},
|
||||
{ ".fods", ".ods "},
|
||||
{ ".fods", ".ots "},
|
||||
{ ".fods", ".pdf "},
|
||||
{ ".fods", ".xlsm "},
|
||||
{ ".fods", ".xlsx "},
|
||||
{ ".fods", ".xltm "},
|
||||
{ ".fods", ".xltx "},
|
||||
{ ".fodt", ".docm "},
|
||||
{ ".fodt", ".docx "},
|
||||
{ ".fodt", ".dotm "},
|
||||
{ ".fodt", ".dotx "},
|
||||
{ ".fodt", ".epub "},
|
||||
{ ".fodt", ".fb2 "},
|
||||
{ ".fodt", ".html "},
|
||||
{ ".fodt", ".odt "},
|
||||
{ ".fodt", ".ott "},
|
||||
{ ".fodt", ".pdf "},
|
||||
{ ".fodt", ".rtf "},
|
||||
{ ".fodt", ".txt "},
|
||||
{ ".html", ".docm "},
|
||||
{ ".html", ".docx "},
|
||||
{ ".html", ".dotm "},
|
||||
{ ".html", ".dotx "},
|
||||
{ ".html", ".epub "},
|
||||
{ ".html", ".fb2 "},
|
||||
{ ".html", ".odt "},
|
||||
{ ".html", ".ott "},
|
||||
{ ".html", ".pdf "},
|
||||
{ ".html", ".rtf "},
|
||||
{ ".html", ".txt "},
|
||||
{ ".mht", ".docm "},
|
||||
{ ".mht", ".docx "},
|
||||
{ ".mht", ".dotm "},
|
||||
{ ".mht", ".dotx "},
|
||||
{ ".mht", ".epub "},
|
||||
{ ".mht", ".fb2 "},
|
||||
{ ".mht", ".odt "},
|
||||
{ ".mht", ".ott "},
|
||||
{ ".mht", ".pdf "},
|
||||
{ ".mht", ".rtf "},
|
||||
{ ".mht", ".txt "},
|
||||
{ ".odp", ".otp "},
|
||||
{ ".odp", ".pdf "},
|
||||
{ ".odp", ".potm "},
|
||||
{ ".odp", ".potx "},
|
||||
{ ".odp", ".ppsm "},
|
||||
{ ".odp", ".ppsx "},
|
||||
{ ".odp", ".pptm "},
|
||||
{ ".odp", ".pptx "},
|
||||
{ ".ods", ".csv "},
|
||||
{ ".ods", ".ots "},
|
||||
{ ".ods", ".pdf "},
|
||||
{ ".ods", ".xlsm "},
|
||||
{ ".ods", ".xlsx "},
|
||||
{ ".ods", ".xltm "},
|
||||
{ ".ods", ".xltx "},
|
||||
{ ".odt", ".docm "},
|
||||
{ ".odt", ".docx "},
|
||||
{ ".odt", ".dotm "},
|
||||
{ ".odt", ".dotx "},
|
||||
{ ".odt", ".epub "},
|
||||
{ ".odt", ".fb2 "},
|
||||
{ ".odt", ".html "},
|
||||
{ ".odt", ".ott "},
|
||||
{ ".odt", ".pdf "},
|
||||
{ ".odt", ".rtf "},
|
||||
{ ".odt", ".txt "},
|
||||
{ ".otp", ".odp "},
|
||||
{ ".otp", ".pdf "},
|
||||
{ ".otp", ".potm "},
|
||||
{ ".otp", ".potx "},
|
||||
{ ".otp", ".ppsm "},
|
||||
{ ".otp", ".ppsx "},
|
||||
{ ".otp", ".pptm "},
|
||||
{ ".otp", ".pptx "},
|
||||
{ ".ots", ".csv "},
|
||||
{ ".ots", ".ods "},
|
||||
{ ".ots", ".pdf "},
|
||||
{ ".ots", ".xlsm "},
|
||||
{ ".ots", ".xlsx "},
|
||||
{ ".ots", ".xltm "},
|
||||
{ ".ots", ".xltx "},
|
||||
{ ".ott", ".docm "},
|
||||
{ ".ott", ".docx "},
|
||||
{ ".ott", ".dotm "},
|
||||
{ ".ott", ".dotx "},
|
||||
{ ".ott", ".epub "},
|
||||
{ ".ott", ".fb2 "},
|
||||
{ ".ott", ".html "},
|
||||
{ ".ott", ".odt "},
|
||||
{ ".ott", ".pdf "},
|
||||
{ ".ott", ".rtf "},
|
||||
{ ".ott", ".txt "},
|
||||
{ ".oxps", ".docm "},
|
||||
{ ".oxps", ".docx "},
|
||||
{ ".oxps", ".dotm "},
|
||||
{ ".oxps", ".dotx "},
|
||||
{ ".oxps", ".epub "},
|
||||
{ ".oxps", ".fb2 "},
|
||||
{ ".oxps", ".html "},
|
||||
{ ".oxps", ".odt "},
|
||||
{ ".oxps", ".ott "},
|
||||
{ ".oxps", ".pdf "},
|
||||
{ ".oxps", ".rtf "},
|
||||
{ ".oxps", ".txt "},
|
||||
{ ".pdf", ".docm "},
|
||||
{ ".pdf", ".docx "},
|
||||
{ ".pdf", ".dotm "},
|
||||
{ ".pdf", ".dotx "},
|
||||
{ ".pdf", ".epub "},
|
||||
{ ".pdf", ".fb2 "},
|
||||
{ ".pdf", ".html "},
|
||||
{ ".pdf", ".odt "},
|
||||
{ ".pdf", ".ott "},
|
||||
{ ".pdf", ".rtf "},
|
||||
{ ".pdf", ".txt "},
|
||||
{ ".pot", ".odp "},
|
||||
{ ".pot", ".otp "},
|
||||
{ ".pot", ".pdf "},
|
||||
{ ".pot", ".potm "},
|
||||
{ ".pot", ".potx "},
|
||||
{ ".pot", ".ppsm "},
|
||||
{ ".pot", ".ppsx "},
|
||||
{ ".pot", ".pptm "},
|
||||
{ ".pot", ".pptx "},
|
||||
{ ".potm", ".odp "},
|
||||
{ ".potm", ".otp "},
|
||||
{ ".potm", ".pdf "},
|
||||
{ ".potm", ".potx "},
|
||||
{ ".potm", ".ppsm "},
|
||||
{ ".potm", ".ppsx "},
|
||||
{ ".potm", ".pptm "},
|
||||
{ ".potm", ".pptx "},
|
||||
{ ".potx", ".odp "},
|
||||
{ ".potx", ".otp "},
|
||||
{ ".potx", ".pdf "},
|
||||
{ ".potx", ".potm "},
|
||||
{ ".potx", ".ppsm "},
|
||||
{ ".potx", ".ppsx "},
|
||||
{ ".potx", ".pptm "},
|
||||
{ ".potx", ".pptx "},
|
||||
{ ".pps", ".odp "},
|
||||
{ ".pps", ".otp "},
|
||||
{ ".pps", ".pdf "},
|
||||
{ ".pps", ".potm "},
|
||||
{ ".pps", ".potx "},
|
||||
{ ".pps", ".ppsm "},
|
||||
{ ".pps", ".ppsx "},
|
||||
{ ".pps", ".pptm "},
|
||||
{ ".pps", ".pptx "},
|
||||
{ ".ppsm", ".odp "},
|
||||
{ ".ppsm", ".otp "},
|
||||
{ ".ppsm", ".pdf "},
|
||||
{ ".ppsm", ".potm "},
|
||||
{ ".ppsm", ".potx "},
|
||||
{ ".ppsm", ".ppsx "},
|
||||
{ ".ppsm", ".pptm "},
|
||||
{ ".ppsm", ".pptx "},
|
||||
{ ".ppsx", ".odp "},
|
||||
{ ".ppsx", ".otp "},
|
||||
{ ".ppsx", ".pdf "},
|
||||
{ ".ppsx", ".potm "},
|
||||
{ ".ppsx", ".potx "},
|
||||
{ ".ppsx", ".ppsm "},
|
||||
{ ".ppsx", ".pptm "},
|
||||
{ ".ppsx", ".pptx "},
|
||||
{ ".ppt", ".odp "},
|
||||
{ ".ppt", ".otp "},
|
||||
{ ".ppt", ".pdf "},
|
||||
{ ".ppt", ".potm "},
|
||||
{ ".ppt", ".potx "},
|
||||
{ ".ppt", ".ppsm "},
|
||||
{ ".ppt", ".ppsx "},
|
||||
{ ".ppt", ".pptm "},
|
||||
{ ".ppt", ".pptx "},
|
||||
{ ".pptm", ".odp "},
|
||||
{ ".pptm", ".otp "},
|
||||
{ ".pptm", ".pdf "},
|
||||
{ ".pptm", ".potm "},
|
||||
{ ".pptm", ".potx "},
|
||||
{ ".pptm", ".ppsm "},
|
||||
{ ".pptm", ".ppsx "},
|
||||
{ ".pptm", ".pptx "},
|
||||
{ ".pptt", ".pptx "},
|
||||
{ ".pptx", ".odp "},
|
||||
{ ".pptx", ".otp "},
|
||||
{ ".pptx", ".pdf "},
|
||||
{ ".pptx", ".potm "},
|
||||
{ ".pptx", ".potx "},
|
||||
{ ".pptx", ".ppsm "},
|
||||
{ ".pptx", ".ppsx "},
|
||||
{ ".pptx", ".pptm "},
|
||||
{ ".rtf", ".docm "},
|
||||
{ ".rtf", ".docx "},
|
||||
{ ".rtf", ".dotm "},
|
||||
{ ".rtf", ".dotx "},
|
||||
{ ".rtf", ".epub "},
|
||||
{ ".rtf", ".fb2 "},
|
||||
{ ".rtf", ".html "},
|
||||
{ ".rtf", ".odt "},
|
||||
{ ".rtf", ".ott "},
|
||||
{ ".rtf", ".pdf "},
|
||||
{ ".rtf", ".txt "},
|
||||
{ ".txt", ".docm "},
|
||||
{ ".txt", ".docx "},
|
||||
{ ".txt", ".dotm "},
|
||||
{ ".txt", ".dotx "},
|
||||
{ ".txt", ".epub "},
|
||||
{ ".txt", ".fb2 "},
|
||||
{ ".txt", ".html "},
|
||||
{ ".txt", ".odt "},
|
||||
{ ".txt", ".ott "},
|
||||
{ ".txt", ".pdf "},
|
||||
{ ".txt", ".rtf "},
|
||||
{ ".xls", ".csv "},
|
||||
{ ".xls", ".ods "},
|
||||
{ ".xls", ".ots "},
|
||||
{ ".xls", ".pdf "},
|
||||
{ ".xls", ".xlsm "},
|
||||
{ ".xls", ".xlsx "},
|
||||
{ ".xls", ".xltm "},
|
||||
{ ".xls", ".xltx "},
|
||||
{ ".xlsm", ".csv "},
|
||||
{ ".xlsm", ".ods "},
|
||||
{ ".xlsm", ".ots "},
|
||||
{ ".xlsm", ".pdf "},
|
||||
{ ".xlsm", ".xlsx "},
|
||||
{ ".xlsm", ".xltm "},
|
||||
{ ".xlsm", ".xltx "},
|
||||
{ ".xlst", ".xlsx "},
|
||||
{ ".xlsx", ".csv "},
|
||||
{ ".xlsx", ".ods "},
|
||||
{ ".xlsx", ".ots "},
|
||||
{ ".xlsx", ".pdf "},
|
||||
{ ".xlsx", ".xlsm "},
|
||||
{ ".xlsx", ".xltm "},
|
||||
{ ".xlsx", ".xltx "},
|
||||
{ ".xlt", ".csv "},
|
||||
{ ".xlt", ".ods "},
|
||||
{ ".xlt", ".ots "},
|
||||
{ ".xlt", ".pdf "},
|
||||
{ ".xlt", ".xlsm "},
|
||||
{ ".xlt", ".xlsx "},
|
||||
{ ".xlt", ".xltm "},
|
||||
{ ".xlt", ".xltx "},
|
||||
{ ".xltm", ".csv "},
|
||||
{ ".xltm", ".ods "},
|
||||
{ ".xltm", ".ots "},
|
||||
{ ".xltm", ".pdf "},
|
||||
{ ".xltm", ".xlsm "},
|
||||
{ ".xltm", ".xlsx "},
|
||||
{ ".xltm", ".xltx "},
|
||||
{ ".xltx", ".csv "},
|
||||
{ ".xltx", ".ods "},
|
||||
{ ".xltx", ".ots "},
|
||||
{ ".xltx", ".pdf "},
|
||||
{ ".xltx", ".xlsm "},
|
||||
{ ".xltx", ".xlsx "},
|
||||
{ ".xltx", ".xltm "},
|
||||
{ ".xml", ".docm "},
|
||||
{ ".xml", ".docx "},
|
||||
{ ".xml", ".dotm "},
|
||||
{ ".xml", ".dotx "},
|
||||
{ ".xml", ".epub "},
|
||||
{ ".xml", ".fb2 "},
|
||||
{ ".xml", ".html "},
|
||||
{ ".xml", ".odt "},
|
||||
{ ".xml", ".ott "},
|
||||
{ ".xml", ".pdf "},
|
||||
{ ".xml", ".rtf "},
|
||||
{ ".xml", ".txt "},
|
||||
{ ".xps", ".docm "},
|
||||
{ ".xps", ".docx "},
|
||||
{ ".xps", ".dotm "},
|
||||
{ ".xps", ".dotx "},
|
||||
{ ".xps", ".epub "},
|
||||
{ ".xps", ".fb2 "},
|
||||
{ ".xps", ".html "},
|
||||
{ ".xps", ".odt "},
|
||||
{ ".xps", ".ott "},
|
||||
{ ".xps", ".pdf "},
|
||||
{ ".xps", ".rtf "},
|
||||
{ ".xps", ".txt" }
|
||||
});
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,7 +23,8 @@
|
||||
"storybook-serve": "yarn workspace @docspace/components run storybook-serve",
|
||||
"test": "yarn workspace @docspace/components test",
|
||||
"wipe": "shx rm -rf node_modules yarn.lock packages/**/node_modules",
|
||||
"debug-info": "auto-changelog --unreleased-only --template debuginfo --output public/debuginfo.md"
|
||||
"debug-info": "auto-changelog --unreleased-only --template debuginfo --output public/debuginfo.md",
|
||||
"licenses-audit": "yarn licenses audit --output-csv=licenses.csv --config=licenses.config.js --summary"
|
||||
},
|
||||
"old-scripts": {
|
||||
"build:test": "yarn workspaces foreach -vptiR --from '{@docspace/client,@docspace/login,@docspace/editor}' run build:test",
|
||||
|
@ -81,6 +81,7 @@
|
||||
"style-loader": "3.3.2",
|
||||
"terser-webpack-plugin": "^5.3.7",
|
||||
"typescript": "^4.9.5",
|
||||
"use-resize-observer": "^9.1.0",
|
||||
"webpack": "5.76.3",
|
||||
"webpack-cli": "4.10.0",
|
||||
"webpack-dev-server": "4.13.1"
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"AboutCompanyAddressTitle": "Ünvan",
|
||||
"AboutCompanyEmailTitle": "e-poçt",
|
||||
"AboutHeader": "Bu proqram haqqında",
|
||||
"DocumentManagement": "Sənədlərin idarə edilməsi",
|
||||
"OnlineEditors": "Onlayn redaktorlar",
|
||||
"Site": "Sayt",
|
||||
"SoftwareLicense": "Proqram təminatı lisenziyası"
|
||||
}
|
||||
|
@ -1 +1,8 @@
|
||||
{}
|
||||
{
|
||||
"ArchiveHeader": "Arxivə köçürülsün?",
|
||||
"ArchiveRoom": "Otağı arxivləşdirmək üzrəsiniz.",
|
||||
"ArchiveRooms": "Otaqları arxivləşdirmək üzrəsiniz.",
|
||||
"RestoreAllRooms": "Bütün otaqları bərpa etmək istədiyinizə əminsiniz?",
|
||||
"RestoreRoom": "Otağı bərpa etmək istədiyinizə əminsiniz?",
|
||||
"RestoreRooms": "Otaqları bərpa etmək istədiyinizə əminsiniz?"
|
||||
}
|
||||
|
@ -1,5 +1,14 @@
|
||||
{
|
||||
"AppointAdmin": "Administratorları təyin edin",
|
||||
"BackupPortal": "DocSpace məlumatlarını yedəkləyin",
|
||||
"ManagePortal": " DocSpace konfiqurasiyasını idarə edin",
|
||||
"ManageUser": "İstifadəçi hesablarını idarə edin"
|
||||
"ChangeInstruction": "DocSpace sahibini dəyişmək üçün lütfən, aşağıda yeni sahibin adını seçin.",
|
||||
"ChangeOwner": "DocSpace sahibini dəyişdirin",
|
||||
"ChangeUser": "İstifadəçini dəyişdirin",
|
||||
"DeactivateOrDeletePortal": "DocSpace-i deaktiv edin və ya silin",
|
||||
"DoTheSame": "Administratorlarla da eyni şeyi edin",
|
||||
"ManagePortal": "DocSpace konfiqurasiyasını idarə edin",
|
||||
"ManageUser": "İstifadəçi hesablarını idarə edin",
|
||||
"NewPortalOwner": "Yeni DocSpace sahibi",
|
||||
"PortalOwnerCan": "DocSpace sahibi edə bilər:",
|
||||
"SetAccessRights": "Giriş hüquqlarını təyin edin"
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user