Merge branch 'feature/file-folder-selectors' of https://github.com/ONLYOFFICE/AppServer into feature/file-folder-selectors

This commit is contained in:
Alexey Safronov 2021-07-28 18:06:00 +03:00
commit 76a82faf23
232 changed files with 19317 additions and 2941 deletions

View File

@ -43,6 +43,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Notify.Textile", "commo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.ElasticSearch", "common\services\ASC.ElasticSearch\ASC.ElasticSearch.csproj", "{AE1A0E06-6CD4-4E1D-8209-22BBBD6D5652}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Calendar", "products\ASC.Calendar\Server\ASC.Calendar.csproj", "{867BF98F-9638-4E99-BB68-651E1B812547}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Files", "products\ASC.Files\Server\ASC.Files.csproj", "{77BA2F61-6155-4283-BB39-F8E42F46A0B0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Files.Service", "products\ASC.Files\Service\ASC.Files.Service.csproj", "{5D41FFFF-816C-40B2-95CD-E2DDDCB83784}"
@ -82,7 +84,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.CRM", "products\ASC.CRM
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Mail", "products\ASC.Mail\Server\ASC.Mail.csproj", "{137CA67B-D0F5-4746-B8BC-1888D2859B90}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Calendar", "products\ASC.Calendar\Server\ASC.Calendar.csproj", "{F39933F8-7598-492F-9DD3-E25780D68288}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Radicale", "common\services\ASC.Radicale\ASC.Radicale.csproj", "{74998718-3C9A-4A89-B834-14453762C60F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.SsoAuth.Svc", "common\services\ASC.SsoAuth.Svc\ASC.SsoAuth.Svc.csproj", "{6AD828EA-FBA2-4D30-B969-756B3BE78E4E}"
EndProject
@ -174,6 +176,10 @@ Global
{AE1A0E06-6CD4-4E1D-8209-22BBBD6D5652}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE1A0E06-6CD4-4E1D-8209-22BBBD6D5652}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE1A0E06-6CD4-4E1D-8209-22BBBD6D5652}.Release|Any CPU.Build.0 = Release|Any CPU
{867BF98F-9638-4E99-BB68-651E1B812547}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{867BF98F-9638-4E99-BB68-651E1B812547}.Debug|Any CPU.Build.0 = Debug|Any CPU
{867BF98F-9638-4E99-BB68-651E1B812547}.Release|Any CPU.ActiveCfg = Release|Any CPU
{867BF98F-9638-4E99-BB68-651E1B812547}.Release|Any CPU.Build.0 = Release|Any CPU
{77BA2F61-6155-4283-BB39-F8E42F46A0B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77BA2F61-6155-4283-BB39-F8E42F46A0B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77BA2F61-6155-4283-BB39-F8E42F46A0B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -238,14 +244,14 @@ Global
{277F4A2C-07CC-4BC5-B4F3-9695BB2DFFB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{277F4A2C-07CC-4BC5-B4F3-9695BB2DFFB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{277F4A2C-07CC-4BC5-B4F3-9695BB2DFFB9}.Release|Any CPU.Build.0 = Release|Any CPU
{74998718-3C9A-4A89-B834-14453762C60F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{74998718-3C9A-4A89-B834-14453762C60F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74998718-3C9A-4A89-B834-14453762C60F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74998718-3C9A-4A89-B834-14453762C60F}.Release|Any CPU.Build.0 = Release|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Debug|Any CPU.Build.0 = Debug|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Release|Any CPU.ActiveCfg = Release|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Release|Any CPU.Build.0 = Release|Any CPU
{F39933F8-7598-492F-9DD3-E25780D68288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F39933F8-7598-492F-9DD3-E25780D68288}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F39933F8-7598-492F-9DD3-E25780D68288}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F39933F8-7598-492F-9DD3-E25780D68288}.Release|Any CPU.Build.0 = Release|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Release|Any CPU.Build.0 = Release|Any CPU
{6AD828EA-FBA2-4D30-B969-756B3BE78E4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6AD828EA-FBA2-4D30-B969-756B3BE78E4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6AD828EA-FBA2-4D30-B969-756B3BE78E4E}.Release|Any CPU.ActiveCfg = Release|Any CPU

View File

@ -10,9 +10,17 @@ package_services="";
RES_APP_INSTALLED="is already installed";
RES_APP_CHECK_PORTS="uses ports"
RES_CHECK_PORTS="please, make sure that the ports are free.";
RES_INSTALL_SUCCESS="Thank you for installing ONLYOFFICE ${product}.";
RES_INSTALL_SUCCESS="Thank you for installing ONLYOFFICE ${product^^}.";
RES_QUESTIONS="In case you have any questions contact us via http://support.onlyoffice.com or visit our forum at http://dev.onlyoffice.org"
res_unsupported_version () {
RES_CHOICE="Please, enter Y or N"
RES_CHOICE_INSTALLATION="Continue installation [Y/N]? "
RES_UNSPPORTED_VERSION="You have an unsupported version of $DIST installed"
RES_SELECT_INSTALLATION="Select 'N' to cancel the ONLYOFFICE installation (recommended). Select 'Y' to continue installing ONLYOFFICE"
RES_ERROR_REMINDER="Please note, that if you continue with the installation, there may be errors"
}
while [ "$1" != "" ]; do
case $1 in

View File

@ -15,6 +15,8 @@ ${package_manager} clean all
${package_manager} -y install yum-utils
DIST=$(rpm -q --whatprovides redhat-release || rpm -q --whatprovides centos-release);
DIST=$(echo $DIST | sed -n '/-.*/s///p');
REV=$(cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//);
REV_PARTS=(${REV//\./ });
REV=${REV_PARTS[0]};
@ -23,6 +25,33 @@ if ! [[ "$REV" =~ ^[0-9]+$ ]]; then
REV=7;
fi
read_unsupported_installation () {
read -p "$RES_CHOICE_INSTALLATION " CHOICE_INSTALLATION
case "$CHOICE_INSTALLATION" in
y|Y ) yum -y install $DIST*-release
;;
n|N ) exit 0;
;;
* ) echo $RES_CHOICE;
read_unsupported_installation
;;
esac
}
{ yum check-update $DIST*-release; exitCode=$?; } || true #Checking for distribution update
UPDATE_AVAILABLE_CODE=100
if [[ $exitCode -eq $UPDATE_AVAILABLE_CODE ]]; then
res_unsupported_version
echo $RES_UNSPPORTED_VERSION
echo $RES_SELECT_INSTALLATION
echo $RES_ERROR_REMINDER
echo $RES_QUESTIONS
read_unsupported_installation
fi
# add epel repo
rpm -ivh https://dl.fedoraproject.org/pub/epel/epel-release-latest-$REV.noarch.rpm || true
rpm -ivh https://rpms.remirepo.net/enterprise/remi-release-$REV.rpm || true
@ -140,7 +169,7 @@ ${package_manager} -y install epel-release \
make \
yarn \
dotnet-sdk-5.0 \
elasticsearch-7.8.1 --enablerepo=elasticsearch \
elasticsearch-7.13.1 --enablerepo=elasticsearch \
mysql-server \
nginx \
supervisor \

View File

@ -42,7 +42,6 @@ done
echo "== BACK-END-BUILD =="
cd ${SRC_PATH}
dotnet restore ASC.Web.sln${ARGS}
dotnet build ASC.Web.sln ${ARGS}
echo "== Build ASC.Thumbnails =="

View File

@ -35,3 +35,4 @@ echo "== FRONT-END-BUILD =="
cd ${SRC_PATH}
yarn install
yarn build
yarn deploy

View File

@ -68,7 +68,7 @@ for i in ${!servers_products_name_backend[@]}; do
echo "== Publish ${servers_products_name_backend[$i]}.csproj project =="
SERVICE_DIR="$(dirname "$(find ${SRC_PATH} -type f -name "${servers_products_name_backend[$i]}".csproj)")"
cd ${SERVICE_DIR}
dotnet publish -c Release --self-contained ${SELF_CONTAINED} ${ARGS} -o ${BUILD_PATH}/products/${servers_products_name_backend[$i]}/server/
dotnet publish -c Release --self-contained ${SELF_CONTAINED} ${ARGS} --no-build -o ${BUILD_PATH}/products/${servers_products_name_backend[$i]}/server/
done
# Array of names backend services
@ -91,7 +91,7 @@ for i in ${!services_name_backend[@]}; do
echo "== Publish ${services_name_backend[$i]}.csproj project =="
SERVICE_DIR="$(dirname "$(find ${SRC_PATH} -type f -name "${services_name_backend[$i]}".csproj)")"
cd ${SERVICE_DIR}
dotnet publish -c Release --self-contained ${SELF_CONTAINED} ${ARGS} -o ${BUILD_PATH}/services/${services_name_backend[$i]}/service/
dotnet publish -c Release --self-contained ${SELF_CONTAINED} ${ARGS} --no-build -o ${BUILD_PATH}/services/${services_name_backend[$i]}/service/
done
# Array of names backend services in directory common (Nodejs)

View File

@ -75,18 +75,18 @@ reassign_values (){
EXEC_FILE="ASC.ApiSystem.dll"
;;
urlshortener )
SERVICE_PORT="9999"
WORK_DIR="${BASE_DIR}/services/ASC.UrlShortener/"
SERVICE_PORT="9998"
WORK_DIR="${BASE_DIR}/services/ASC.UrlShortener.Svc/"
EXEC_FILE="ASC.UrlShortener.Svc.dll"
;;
thumbnails )
SERVICE_PORT="9800"
WORK_DIR="${BASE_DIR}/services/ASC.Thumbnails/"
SERVICE_PORT="9799"
WORK_DIR="${BASE_DIR}/services/ASC.Thumbnails.Svc/"
EXEC_FILE="ASC.Thumbnails.Svc.dll"
;;
socket )
SERVICE_PORT="9899"
WORK_DIR="${BASE_DIR}/services/ASC.Socket.IO/"
SERVICE_PORT="9898"
WORK_DIR="${BASE_DIR}/services/ASC.Socket.IO.Svc/"
EXEC_FILE="ASC.Socket.IO.Svc.dll"
;;
studio-notify )

View File

@ -7,6 +7,8 @@ ARG REPO=mcr.microsoft.com/dotnet/sdk
FROM $REPO:$REPO_TAG AS base
ARG RELEASE_DATE="2016-06-21"
ARG DEBIAN_FRONTEND=noninteractive
ARG PRODUCT_VERSION=0.0.0
ARG BUILD_NUMBER=0
ARG GIT_BRANCH=master
ARG SRC_PATH
ARG BUILD_PATH
@ -27,8 +29,10 @@ RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
adduser -uid 104 --quiet --home /var/www/onlyoffice --system --gid 107 onlyoffice && \
locale-gen en_US.UTF-8 && \
apt-get -y update && \
apt-get install -yq git apt-utils npm nodejs && \
npm install --global yarn
apt-get install -yq git apt-utils npm && \
npm install --global yarn && \
curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash - && \
apt-get install -y nodejs
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
echo ${GIT_BRANCH} && \
@ -36,15 +40,15 @@ RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
cd ${SRC_PATH} && \
mkdir -p /var/www/public/ && cp -rf public/* /var/www/public/ && \
mkdir -p /app/onlyoffice/config/ && cp -rf config/* /app/onlyoffice/config/ && \
mkdir -p /etc/nginx/conf.d && cp -f config/nginx/onlyoffice*.conf /etc/nginx/conf.d/ && \
mkdir -p /etc/nginx/includes/ && cp -f config/nginx/includes/onlyoffice*.conf /etc/nginx/includes/ && \
sed -i "s/\"number\".*,/\"number\": \"${PRODUCT_VERSION}.${BUILD_NUMBER}\",/g" /app/onlyoffice/config/appsettings.json && \
sed -e 's/#//' -i /etc/nginx/conf.d/onlyoffice.conf && \
cd ${SRC_PATH}/build/install/common/ && \
bash build-frontend.sh -sp ${SRC_PATH} && \
bash build-backend.sh -sp ${SRC_PATH} -ar "--disable-parallel" && \
bash publish-backend.sh -sp ${SRC_PATH} -bp ${BUILD_PATH} -ar "--disable-parallel" && \
bash build-backend.sh -sp ${SRC_PATH} && \
bash publish-backend.sh -sp ${SRC_PATH} -bp ${BUILD_PATH} && \
cp -rf ${SRC_PATH}/products/ASC.Files/Server/DocStore ${BUILD_PATH}/products/ASC.Files/server/ && \
rm -rf ${SRC_PATH}/common/* && \
rm -rf ${SRC_PATH}/web/ASC.Web.Core/* && \
@ -112,17 +116,9 @@ RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
# copy static services files and config values
COPY --from=base /etc/nginx/conf.d /etc/nginx/conf.d
COPY --from=base /etc/nginx/includes /etc/nginx/includes
COPY --from=base /var/www/public /var/www/public
COPY --from=base ${SRC_PATH}/products/ASC.CRM/Client/dist ${BUILD_PATH}/products/ASC.CRM/client
COPY --from=base ${SRC_PATH}/web/ASC.Web.Editor/dist ${BUILD_PATH}/products/ASC.Files/editor
COPY --from=base ${SRC_PATH}/products/ASC.Files/Client/dist ${BUILD_PATH}/products/ASC.Files/client
COPY --from=base ${SRC_PATH}/web/ASC.Web.Login/dist ${BUILD_PATH}/studio/login
COPY --from=base ${SRC_PATH}/products/ASC.People/Client/dist ${BUILD_PATH}/products/ASC.People/client
COPY --from=base ${SRC_PATH}/products/ASC.Projects/Client/dist ${BUILD_PATH}/products/ASC.Projects/client
COPY --from=base ${SRC_PATH}/web/ASC.Web.Client/dist ${BUILD_PATH}/studio/client
COPY --from=base ${SRC_PATH}/products/ASC.Calendar/Client/dist ${BUILD_PATH}/products/ASC.Calendar/client
COPY --from=base ${SRC_PATH}/products/ASC.Mail/Client/dist ${BUILD_PATH}/products/ASC.Mail/client
COPY --from=base ${SRC_PATH}/build/deploy/products ${BUILD_PATH}/products
COPY --from=base ${SRC_PATH}/build/deploy/public ${BUILD_PATH}/public
COPY --from=base ${SRC_PATH}/build/deploy/studio ${BUILD_PATH}/studio
COPY /config/nginx/templates/upstream.conf.template /etc/nginx/templates/upstream.conf.template
COPY /config/nginx/templates/nginx.conf.template /etc/nginx/nginx.conf.template
COPY prepare-nginx-proxy.sh /docker-entrypoint.d/prepare-nginx-proxy.sh

View File

@ -1,3 +1,7 @@
#!/bin/bash
export SRV_VERSION=$DOCKER_TAG
docker-compose -f build.yml build --build-arg GIT_BRANCH=$SOURCE_BRANCH
BUILD_NUMBER="$(date "+%Y%m%d%H")"
docker-compose -f build.yml build \
--build-arg GIT_BRANCH=$SOURCE_BRANCH \
--build-arg PRODUCT_VERSION=$PRODUCT_VERSION \
--build-arg BUILD_NUMBER=$BUILD_NUMBER

View File

@ -13,7 +13,7 @@ Packager: Ascensio System SIA <support@onlyoffice.com>
ExclusiveArch: x86_64
AutoReq: no
AutoProv: no
License: GPLv3
License: AGPLv3
Source0: https://github.com/ONLYOFFICE/%{product}/archive/%GIT_BRANCH.tar.gz
BuildRequires: nodejs >= 12.0
BuildRequires: yarn

View File

@ -166,18 +166,21 @@
%files urlshortener
%defattr(-, onlyoffice, onlyoffice, -)
%{buildpath}/services/ASC.UrlShortener/
%{buildpath}/services/ASC.UrlShortener.Svc/
%{_sysconfdir}/systemd/system/%{product}-urlshortener.service
%dir %{buildpath}/services/
%files thumbnails
%defattr(-, onlyoffice, onlyoffice, -)
%{buildpath}/services/ASC.Thumbnails/
%{buildpath}/services/ASC.Thumbnails.Svc/
%{_sysconfdir}/systemd/system/%{product}-thumbnails.service
%dir %{buildpath}/services/
%files socket
%defattr(-, onlyoffice, onlyoffice, -)
%{buildpath}/services/ASC.Socket.IO/
%{buildpath}/services/ASC.Socket.IO.Svc/
%{buildpath}/products/ASC.Files/server/
%{buildpath}/products/ASC.People/server/
%{buildpath}/products/ASC.CRM/server/

View File

@ -13,7 +13,7 @@ mkdir -p "%{buildroot}%{buildpath}/products/ASC.CRM/client/"
mkdir -p "%{buildroot}%{buildpath}/products/ASC.CRM/server/"
mkdir -p "%{buildroot}%{buildpath}/products/ASC.Files/client/"
mkdir -p "%{buildroot}%{buildpath}/products/ASC.Files/editor/"
mkdir -p "%{buildroot}%{buildpath}/products/ASC.Files/server/"
mkdir -p "%{buildroot}%{buildpath}/products/ASC.Files/server/DocStore/"
mkdir -p "%{buildroot}%{buildpath}/products/ASC.Files/service/"
mkdir -p "%{buildroot}%{buildpath}/products/ASC.Mail/client/"
mkdir -p "%{buildroot}%{buildpath}/products/ASC.Mail/server/"
@ -23,6 +23,7 @@ mkdir -p "%{buildroot}%{buildpath}/products/ASC.Projects/client/"
mkdir -p "%{buildroot}%{buildpath}/products/ASC.Projects/server/"
mkdir -p "%{buildroot}%{buildpath}/public/"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.Socket.IO/"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.Socket.IO.Svc/"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.ApiSystem/"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.Data.Backup/"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.Notify/"
@ -30,8 +31,10 @@ mkdir -p "%{buildroot}%{buildpath}/services/ASC.Data.Storage.Encryption/service"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.Data.Storage.Migration/service"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.Studio.Notify/"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.TelegramService/"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.Thumbnails/client/"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.UrlShortener/client/"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.Thumbnails/"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.UrlShortener/"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.UrlShortener.Svc/"
mkdir -p "%{buildroot}%{buildpath}/services/ASC.Thumbnails.Svc/"
mkdir -p "%{buildroot}%{buildpath}/sql/"
mkdir -p "%{buildroot}%{buildpath}/studio/api/"
mkdir -p "%{buildroot}%{buildpath}/studio/client/"
@ -48,15 +51,15 @@ cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.ApiSystem/service/* "%{bu
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Data.Backup/service/* "%{buildroot}%{buildpath}/services/ASC.Data.Backup/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Notify/service/* "%{buildroot}%{buildpath}/services/ASC.Notify/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Socket.IO/service/* "%{buildroot}%{buildpath}/services/ASC.Socket.IO/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Socket.IO.Svc/service/* "%{buildroot}%{buildpath}/services/ASC.Socket.IO/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Socket.IO.Svc/service/* "%{buildroot}%{buildpath}/services/ASC.Socket.IO.Svc/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Data.Storage.Encryption/service/* "%{buildroot}%{buildpath}/services/ASC.Data.Storage.Encryption/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Data.Storage.Migration/service/* "%{buildroot}%{buildpath}/services/ASC.Data.Storage.Migration/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Studio.Notify/service/* "%{buildroot}%{buildpath}/services/ASC.Studio.Notify/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.TelegramService/service/* "%{buildroot}%{buildpath}/services/ASC.TelegramService/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Thumbnails/service/* "%{buildroot}%{buildpath}/services/ASC.Thumbnails/client/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Thumbnails.Svc/service/* "%{buildroot}%{buildpath}/services/ASC.Thumbnails/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.UrlShortener/service/* "%{buildroot}%{buildpath}/services/ASC.UrlShortener/client/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.UrlShortener.Svc/service/* "%{buildroot}%{buildpath}/services/ASC.UrlShortener/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Thumbnails/service/* "%{buildroot}%{buildpath}/services/ASC.Thumbnails/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Thumbnails.Svc/service/* "%{buildroot}%{buildpath}/services/ASC.Thumbnails.Svc/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.UrlShortener/service/* "%{buildroot}%{buildpath}/services/ASC.UrlShortener/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.UrlShortener.Svc/service/* "%{buildroot}%{buildpath}/services/ASC.UrlShortener.Svc/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Web.Api/service/* "%{buildroot}%{buildpath}/studio/api/"
cp -rf %{_builddir}/%{sourcename}/publish/services/ASC.Web.Studio/service/* "%{buildroot}%{buildpath}/studio/server/"
cp -rf %{_builddir}/%{sourcename}/build/install/common/systemd/modules/* "%{buildroot}%{_sysconfdir}/systemd/system/"
@ -67,6 +70,7 @@ cp -rf %{_builddir}/%{sourcename}/config/nginx/includes/onlyoffice*.conf "%{buil
cp -rf %{_builddir}/%{sourcename}/config/nginx/onlyoffice*.conf "%{buildroot}%{_sysconfdir}/nginx/conf.d/"
cp -rf %{_builddir}/%{sourcename}/products/ASC.CRM/Client/dist/* "%{buildroot}%{buildpath}/products/ASC.CRM/client/"
cp -rf %{_builddir}/%{sourcename}/products/ASC.Files/Client/dist/* "%{buildroot}%{buildpath}/products/ASC.Files/client/"
cp -rf %{_builddir}/%{sourcename}/products/ASC.Files/Server/DocStore/* "%{buildroot}%{buildpath}/products/ASC.Files/server/DocStore/"
cp -rf %{_builddir}/%{sourcename}/products/ASC.People/Client/dist/* "%{buildroot}%{buildpath}/products/ASC.People/client/"
cp -rf %{_builddir}/%{sourcename}/products/ASC.Projects/Client/dist/* "%{buildroot}%{buildpath}/products/ASC.Projects/client/"
cp -rf %{_builddir}/%{sourcename}/products/ASC.Calendar/Client/dist/* "%{buildroot}%{buildpath}/products/ASC.Calendar/client/"

View File

@ -31,7 +31,6 @@ ELK_PORT="9200"
JSON="json -I -f"
JSON_USERCONF="$JSON $USER_CONF -e"
JSON_DSCONF="$JSON $DS_CONF -e"
[ $(id -u) -ne 0 ] && { echo "Root privileges required"; exit 1; }
@ -129,7 +128,7 @@ while [ "$1" != "" ]; do
echo " -zkp, --zookeeperport zookeeper port (default 2181)"
echo " -esh, --elastichost elasticsearch ip"
echo " -esp, --elasticport elasticsearch port (default 9200)"
echo " -e, --environment environment (default 'production')"
echo " -e, --environment environment (default 'production')"
echo " -?, -h, --help this help"
echo
exit 0
@ -167,8 +166,8 @@ install_json() {
set_core_machinekey
$JSON_USERCONF "this.core={'base-domain': \"$APP_HOST\", 'machinekey': \"$CORE_MACHINEKEY\" }" \
-e "this.urlshortener={ 'path': 'client/index.js' }" -e "this.thumb={ 'path': 'client/' }" \
-e "this.socket={ 'path': '../ASC.Socket.IO' }" >/dev/null 2>&1
-e "this.urlshortener={ 'path': '../ASC.UrlShortener/index.js' }" -e "this.thumb={ 'path': '../ASC.Thumbnails/' }" \
-e "this.socket={ 'path': '../ASC.Socket.IO/' }" >/dev/null 2>&1
$JSON $APP_DIR/appsettings.json -e "this.core.products.subfolder='server'" >/dev/null 2>&1
$JSON $APP_DIR/appsettings.services.json -e "this.core={ 'products': { 'folder': '../../products', 'subfolder': 'server'} }" >/dev/null 2>&1
@ -178,23 +177,21 @@ install_json() {
restart_services() {
echo -n "Restarting services... "
sed -i "s/ENVIRONMENT=.*/ENVIRONMENT=$ENVIRONMENT/" $SYSTEMD_DIR/${PRODUCT}*.service >/dev/null 2>&1
systemctl daemon-reload
for SVC in nginx mysqld ${PRODUCT}-api ${PRODUCT}-api-system ${PRODUCT}-urlshortener ${PRODUCT}-thumbnails \
${PRODUCT}-socket ${PRODUCT}-studio-notify ${PRODUCT}-notify ${PRODUCT}-people-server ${PRODUCT}-files \
${PRODUCT}-files-services ${PRODUCT}-studio ${PRODUCT}-backup ${PRODUCT}-storage-encryption \
${PRODUCT}-storage-migration ${PRODUCT}-projects-server ${PRODUCT}-telegram-service ${PRODUCT}-crm \
${PRODUCT}-calendar ${PRODUCT}-mail elasticsearch kafka zookeeper
do
sed -i "s/ENVIRONMENT=.*/ENVIRONMENT=$ENVIRONMENT/" $SYSTEMD_DIR/$SVC.service >/dev/null 2>&1
if systemctl is-active $SVC | grep -q "active"; then
systemctl restart $SVC.service >/dev/null 2>&1
else
systemctl enable $SVC.service >/dev/null 2>&1
systemctl start $SVC.service >/dev/null 2>&1
fi
if systemctl is-active $SVC | grep -v "active" >/dev/null; then
echo -e "\033[31m $SVC not started \033[0m"
fi
done
echo "OK"
}
@ -418,6 +415,7 @@ setup_nginx(){
setup_docs() {
echo -n "Configuring Docs... "
local DS_CONF="/etc/onlyoffice/documentserver/local.json"
local JSON_DSCONF="$JSON $DS_CONF -e"
#Changing the Docs port in nginx conf
sed -i "s/0.0.0.0:.*;/0.0.0.0:$DOCUMENT_SERVER_PORT;/" $NGINX_CONF/ds.conf
@ -504,7 +502,7 @@ setup_elasticsearch() {
echo -n "Configuring elasticsearch... "
#Save elasticsearch parameters in .json
$JSON_USERCONF "this.elastic={'Scheme': \"${ELK_SHEME}\",'Host': \"${ELK_HOST}\",'Port': \"${ELK_PORT}\" }" >/dev/null 2>&1
$JSON $APP_DIR/elastic.json -e "this.elastic={'Scheme': \"${ELK_SHEME}\",'Host': \"${ELK_HOST}\",'Port': \"${ELK_PORT}\",'Threads': \"1\" }" >/dev/null 2>&1
change_elasticsearch_config
@ -515,12 +513,14 @@ setup_kafka() {
local KAFKA_SERVICE=$(systemctl --type=service | grep 'kafka' | tr -d '●' | awk '{print $1;}')
if [ $KAFKA_SERVICE ]; then
if [ -n ${KAFKA_SERVICE} ]; then
echo -n "Configuring kafka... "
local KAFKA_DIR="$(cat $SYSTEMD_DIR/$KAFKA_SERVICE | grep ExecStop= | cut -c 10- | rev | cut -c 26- | rev)"
local KAFKA_CONF="${KAFKA_DIR}/config"
#Change kafka config
local KAFKA_CONF="$(cat $SYSTEMD_DIR/$KAFKA_SERVICE | grep ExecStop= | cut -c 10- | rev | cut -c 26- | rev)/config"
sed -i "s/clientPort=.*/clientPort=${ZOOKEEPER_PORT}/g" $KAFKA_CONF/zookeeper.properties
sed -i "s/zookeeper.connect=.*/zookeeper.connect=${ZOOKEEPER_HOST}:${ZOOKEEPER_PORT}/g" $KAFKA_CONF/server.properties
sed -i "s/bootstrap.servers=.*/bootstrap.servers=${KAFKA_HOST}:${KAFKA_PORT}/g" $KAFKA_CONF/consumer.properties
@ -532,6 +532,17 @@ setup_kafka() {
#Save kafka parameters in .json
$JSON_USERCONF "this.kafka={'BootstrapServers': \"${KAFKA_HOST}:${KAFKA_PORT}\"}" >/dev/null 2>&1
#Add topics for kafka
KAFKA_TOPICS=( ascchannelQuotaCacheItemAny
ascchannelTariffCacheItemRemove
ascchannelTenantCacheItemInsertOrUpdate
ascchannelTenantSettingRemove )
for i in "${KAFKA_TOPICS[@]}"
do
${KAFKA_DIR}/bin/kafka-topics.sh --create --zookeeper ${ZOOKEEPER_HOST}:${ZOOKEEPER_PORT} --topic $i --replication-factor 1 --partitions 3 >/dev/null 2>&1
done
echo "OK"
fi

2
build/run/Radicale.bat Normal file
View File

@ -0,0 +1,2 @@
echo "RUN ASC.Radicale"
call dotnet run --project ..\..\common\services\ASC.Radicale\ASC.Radicale.csproj --no-build --$STORAGE_ROOT=..\..\Data --log__dir=..\..\Logs --log__name=radicale

View File

@ -8,7 +8,6 @@ using ASC.Api.Core.Middleware;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Mapping;
using Autofac;
@ -34,10 +33,11 @@ namespace ASC.Api.Core
{
public IConfiguration Configuration { get; }
public IHostEnvironment HostEnvironment { get; }
public virtual string[] LogParams { get; }
public virtual JsonConverter[] Converters { get; }
public virtual bool AddControllersAsServices { get; } = false;
public virtual bool ConfirmAddScheme { get; } = false;
protected DIHelper DIHelper { get; }
public virtual bool AddAndUseSession { get; } = false;
protected DIHelper DIHelper { get; }
protected bool LoadProducts { get; } = true;
protected bool LoadConsumers { get; } = true;
@ -49,27 +49,30 @@ namespace ASC.Api.Core
}
public virtual void ConfigureServices(IServiceCollection services)
{
{
services.AddCustomHealthCheck(Configuration);
services.AddHttpContextAccessor();
services.AddMemoryCache();
if(AddAndUseSession)
services.AddSession();
DIHelper.Configure(services);
services.AddControllers()
.AddXmlSerializerFormatters()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.WriteIndented = false;
options.JsonSerializerOptions.IgnoreNullValues = true;
services.AddControllers()
.AddXmlSerializerFormatters()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.WriteIndented = false;
options.JsonSerializerOptions.IgnoreNullValues = true;
options.JsonSerializerOptions.Converters.Add(new ApiDateTimeConverter());
if (Converters != null)
{
{
foreach (var c in Converters)
{
options.JsonSerializerOptions.Converters.Add(c);
}
}
}
});
@ -83,19 +86,22 @@ namespace ASC.Api.Core
DIHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCache<>));
DIHelper.RegisterProducts(Configuration, HostEnvironment.ContentRootPath);
if (LoadProducts)
{
DIHelper.RegisterProducts(Configuration, HostEnvironment.ContentRootPath);
}
var builder = services.AddMvcCore(config =>
{
{
config.Conventions.Add(new ControllerNameAttributeConvention());
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
config.Filters.Add(new AuthorizeFilter(policy));
config.Filters.Add(new TypeFilterAttribute(typeof(TenantStatusFilter)));
config.Filters.Add(new TypeFilterAttribute(typeof(PaymentFilter)));
config.Filters.Add(new TypeFilterAttribute(typeof(IpSecurityFilter)));
config.Filters.Add(new TypeFilterAttribute(typeof(ProductSecurityFilter)));
config.Filters.Add(new AuthorizeFilter(policy));
config.Filters.Add(new TypeFilterAttribute(typeof(TenantStatusFilter)));
config.Filters.Add(new TypeFilterAttribute(typeof(PaymentFilter)));
config.Filters.Add(new TypeFilterAttribute(typeof(IpSecurityFilter)));
config.Filters.Add(new TypeFilterAttribute(typeof(ProductSecurityFilter)));
config.Filters.Add(new CustomResponseFilterAttribute());
config.Filters.Add(new CustomExceptionFilterAttribute());
config.Filters.Add(new TypeFilterAttribute(typeof(FormatFilter)));
@ -113,11 +119,6 @@ namespace ASC.Api.Core
authBuilder.AddScheme<AuthenticationSchemeOptions, ConfirmAuthHandler>("confirm", a => { });
}
if (LogParams != null)
{
LogNLogExtension.ConfigureLog(DIHelper, LogParams);
}
services.AddAutoMapper(Assembly.GetAssembly(typeof(MappingProfile)));
}
@ -129,6 +130,9 @@ namespace ASC.Api.Core
});
app.UseRouting();
if (AddAndUseSession)
app.UseSession();
app.UseAuthentication();
@ -141,7 +145,7 @@ namespace ASC.Api.Core
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapCustom();
endpoints.MapCustom();
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{

View File

@ -98,7 +98,9 @@ namespace ASC.Common.Logging
void FatalFormat(IFormatProvider provider, string format, params object[] args);
string LogDirectory { get; }
string Name { get; set; }
string Name { get; set; }
void Configure(string name);
}
public class Log : ILog
@ -108,7 +110,7 @@ namespace ASC.Common.Logging
XmlConfigurator.Configure(log4net.LogManager.GetRepository(Assembly.GetCallingAssembly()));
}
private readonly log4net.ILog loger;
private log4net.ILog loger;
public bool IsDebugEnabled { get; private set; }
@ -124,6 +126,11 @@ namespace ASC.Common.Logging
public Log(string name)
{
Configure(name);
}
public void Configure(string name)
{
loger = log4net.LogManager.GetLogger(Assembly.GetCallingAssembly(), name);
IsDebugEnabled = loger.IsDebugEnabled;
@ -131,8 +138,8 @@ namespace ASC.Common.Logging
IsWarnEnabled = loger.IsWarnEnabled;
IsErrorEnabled = loger.IsErrorEnabled;
IsFatalEnabled = loger.IsFatalEnabled;
IsTraceEnabled = loger.Logger.IsEnabledFor(Level.Trace);
}
IsTraceEnabled = loger.Logger.IsEnabledFor(Level.Trace);
}
public void Trace(object message)
{
@ -401,14 +408,21 @@ namespace ASC.Common.Logging
NLog.Targets.Target.Register<SelfCleaningTarget>("SelfCleaning");
}
public void Configure(LogNLog options)
{
public void Configure(LogNLog options)
{
options.Configure("ASC");
}
public void Configure(string name, LogNLog options)
{
Configure(options);
if (string.IsNullOrEmpty(name))
{
Configure(options);
}
else
{
options.Configure(name);
}
}
}
@ -443,7 +457,12 @@ namespace ASC.Common.Logging
public bool IsFatalEnabled { get; private set; }
public bool IsTraceEnabled { get; private set; }
public bool IsTraceEnabled { get; private set; }
public void Configure(string name)
{
Name = name;
}
public void Trace(object message)
{
@ -850,19 +869,23 @@ namespace ASC.Common.Logging
public void DebugWithProps(string message, KeyValuePair<string, object> prop1, KeyValuePair<string, object> prop2, KeyValuePair<string, object> prop3)
{
}
}
public void Configure(string name)
{
}
public string LogDirectory { get { return ""; } }
public string Name { get; set; }
}
[Singletone]
public class LogManager<T> : OptionsMonitor<T> where T : class, ILog, new()
{
public LogManager(IOptionsFactory<T> factory, IEnumerable<IOptionsChangeTokenSource<T>> sources, IOptionsMonitorCache<T> cache) : base(factory, sources, cache)
{
{
}
public override T Get(string name)
@ -881,21 +904,8 @@ namespace ASC.Common.Logging
public class LoggerExtension<T> where T : class, ILog, new()
{
public static void RegisterLog(DIHelper services)
{
const string baseName = "ASC";
var baseSqlName = $"{baseName}.SQL";
services.Configure<T>(r => r.Name = baseName);
services.Configure<T>(baseName, r => r.Name = baseName);
services.Configure<T>(baseSqlName, r => r.Name = baseSqlName);
services.TryAdd(typeof(IOptionsMonitor<ILog>), typeof(LogManager<T>));
}
public static void ConfigureLog(DIHelper services, params string[] additionalLoggers)
{
foreach (var l in additionalLoggers)
{
services.Configure<T>(l, r => r.Name = l);
}
services.TryAdd(typeof(IOptionsMonitor<ILog>), typeof(LogManager<T>));
}
}

View File

@ -67,7 +67,8 @@ namespace ASC.Common.Utils
{
try
{
var payloadParts = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(signature)).Split('?');
var rightSignature = signature.Replace("\"", "");
var payloadParts = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(rightSignature)).Split('?');
if (GetHashBase64(payloadParts[1] + secret) == payloadParts[0])
{
//Sig correct

View File

@ -147,6 +147,11 @@ namespace ASC.Common.Utils
public TimeZoneInfo GetTimeZone(string timeZoneId, bool defaultIfNoMatch = true)
{
var defaultTimezone = GetTimeZoneDefault();
if (string.IsNullOrEmpty(timeZoneId))
{
return defaultIfNoMatch ? defaultTimezone : null;
}
try
{

View File

@ -262,7 +262,8 @@ namespace ASC.Core
public string AuthenticateMe(Guid userId, List<Claim> additionalClaims = null)
{
return AuthenticateMe(Authentication.GetAccountByID(TenantManager.GetCurrentTenant().TenantId, userId), additionalClaims);
var account = Authentication.GetAccountByID(TenantManager.GetCurrentTenant().TenantId, userId);
return AuthenticateMe(account, additionalClaims);
}
public void Logout()

View File

@ -40,10 +40,12 @@ namespace ASC.Core.Data
{
private Expression<Func<Subscription, SubscriptionRecord>> FromSubscriptionToSubscriptionRecord { get; set; }
private Expression<Func<DbSubscriptionMethod, SubscriptionMethod>> FromDbSubscriptionMethodToSubscriptionMethod { get; set; }
private UserDbContext UserDbContext { get; set; }
private Lazy<UserDbContext> LazyUserDbContext { get; }
private UserDbContext UserDbContext { get => LazyUserDbContext.Value; }
public DbSubscriptionService(DbContextManager<UserDbContext> dbContextManager)
{
UserDbContext = dbContextManager.Value;
LazyUserDbContext = new Lazy<UserDbContext>(() => dbContextManager.Value);
FromSubscriptionToSubscriptionRecord = r => new SubscriptionRecord
{

View File

@ -61,7 +61,7 @@ namespace ASC.Core.Common.EF
switch (Provider)
{
case Provider.MySql:
optionsBuilder.UseMySql(ConnectionStringSettings.ConnectionString, ServerVersion.AutoDetect(ConnectionStringSettings.ConnectionString), r=>
optionsBuilder.UseMySql(ConnectionStringSettings.ConnectionString, ServerVersion.Parse("8.0.25"), r=>
{
if (!string.IsNullOrEmpty(MigrateAssembly))
{

View File

@ -40,7 +40,8 @@ using ASC.Core.Users;
using Microsoft.Extensions.Options;
namespace ASC.Core
{
{
[Scope]
class ConfigureHostedSolution : IConfigureNamedOptions<HostedSolution>
{
private UserFormatter UserFormatter { get; }

View File

@ -48,12 +48,13 @@ namespace ASC.Feed.Data
private AuthContext AuthContext { get; }
private TenantManager TenantManager { get; }
private TenantUtil TenantUtil { get; }
private FeedDbContext FeedDbContext { get; }
private Lazy<FeedDbContext> LazyFeedDbContext { get; }
private FeedDbContext FeedDbContext { get => LazyFeedDbContext.Value; }
public FeedAggregateDataProvider(AuthContext authContext, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FeedDbContext> dbContextManager)
: this(authContext, tenantManager, tenantUtil)
{
FeedDbContext = dbContextManager.Get(Constants.FeedDbId);
LazyFeedDbContext = new Lazy<FeedDbContext>(() => dbContextManager.Get(Constants.FeedDbId));
}
public FeedAggregateDataProvider(AuthContext authContext, TenantManager tenantManager, TenantUtil tenantUtil)

View File

@ -41,13 +41,14 @@ namespace ASC.Feed.Data
private AuthContext AuthContext { get; }
private TenantManager TenantManager { get; }
private FeedDbContext FeedDbContext { get; }
private Lazy<FeedDbContext> LazyFeedDbContext { get; }
private FeedDbContext FeedDbContext { get => LazyFeedDbContext.Value; }
public FeedReadedDataProvider(AuthContext authContext, TenantManager tenantManager, DbContextManager<FeedDbContext> dbContextManager)
{
AuthContext = authContext;
TenantManager = tenantManager;
FeedDbContext = dbContextManager.Get(dbId);
LazyFeedDbContext = new Lazy<FeedDbContext>(() => dbContextManager.Get(dbId));
}
public DateTime GetTimeReaded()

View File

@ -24,6 +24,7 @@
*/
using System;
using System.Collections.Generic;
using System.Linq;
@ -39,11 +40,12 @@ namespace ASC.IPSecurity
{
private const string dbId = "core";
private TenantDbContext TenantDbContext { get; }
private Lazy<TenantDbContext> LazyTenantDbContext { get; }
private TenantDbContext TenantDbContext { get => LazyTenantDbContext.Value; }
public IPRestrictionsRepository(DbContextManager<TenantDbContext> dbContextManager)
{
TenantDbContext = dbContextManager.Get(dbId);
LazyTenantDbContext = new Lazy<TenantDbContext>(() => dbContextManager.Get(dbId));
}
public List<IPRestriction> Get(int tenant)

View File

@ -36,11 +36,12 @@ namespace ASC.VoipService.Dao
{
private readonly string dbid = "default";
protected VoipDbContext VoipDbContext { get; set; }
private Lazy<VoipDbContext> LazyVoipDbContext { get; }
protected VoipDbContext VoipDbContext { get => LazyVoipDbContext.Value; }
protected AbstractDao(DbContextManager<VoipDbContext> dbOptions, TenantManager tenantManager)
{
VoipDbContext = dbOptions.Get(dbid);
LazyVoipDbContext = new Lazy<VoipDbContext>(() => dbOptions.Get(dbid));
TenantID = tenantManager.GetCurrentTenant().TenantId;
}

View File

@ -30,7 +30,6 @@ using ASC.ApiSystem.Controllers;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using Autofac;
@ -82,8 +81,6 @@ namespace ASC.ApiSystem
services.AddAuthentication()
.AddScheme<AuthenticationSchemeOptions, AuthHandler>("auth.allowskip", _ => { })
.AddScheme<AuthenticationSchemeOptions, AuthHandler>("auth.allowskip.registerportal", _ => { });
LogNLogExtension.ConfigureLog(diHelper, "ASC.Apisystem");
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

View File

@ -44,14 +44,15 @@ namespace ASC.AuditTrail
{
private MessageTarget MessageTarget { get; set; }
private UserFormatter UserFormatter { get; set; }
private AuditTrailContext AuditTrailContext { get; }
private Lazy<AuditTrailContext> LazyAuditTrailContext { get; }
private AuditTrailContext AuditTrailContext { get => LazyAuditTrailContext.Value; }
private AuditActionMapper AuditActionMapper { get; }
public AuditEventsRepository(MessageTarget messageTarget, UserFormatter userFormatter, DbContextManager<AuditTrailContext> dbContextManager, AuditActionMapper auditActionMapper)
{
MessageTarget = messageTarget;
UserFormatter = userFormatter;
AuditTrailContext = dbContextManager.Value;
LazyAuditTrailContext = new Lazy<AuditTrailContext>(() => dbContextManager.Value );
AuditActionMapper = auditActionMapper;
}

View File

@ -43,14 +43,15 @@ namespace ASC.AuditTrail.Data
[Scope]
public class LoginEventsRepository
{
private UserFormatter UserFormatter { get; }
private AuditTrailContext AuditTrailContext { get; }
private UserFormatter UserFormatter { get; }
private Lazy<AuditTrailContext> LazyAuditTrailContext { get; }
private AuditTrailContext AuditTrailContext { get => LazyAuditTrailContext.Value; }
private AuditActionMapper AuditActionMapper { get; }
public LoginEventsRepository(UserFormatter userFormatter, DbContextManager<AuditTrailContext> dbContextManager, AuditActionMapper auditActionMapper)
{
UserFormatter = userFormatter;
AuditTrailContext = dbContextManager.Value;
LazyAuditTrailContext = new Lazy<AuditTrailContext>(() => dbContextManager.Value);
AuditActionMapper = auditActionMapper;
}

View File

@ -31,7 +31,6 @@ using System.Threading.Tasks;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using Autofac;
@ -84,7 +83,6 @@ namespace ASC.Thumbnails.Svc
var diHelper = new DIHelper(services);
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCache<>));
LogNLogExtension.ConfigureLog(diHelper, "ASC.ClearEvents");
services.AddHostedService<ClearEventsServiceLauncher>();
diHelper.TryAdd<ClearEventsServiceLauncher>();
})

View File

@ -38,8 +38,6 @@ namespace ASC.Data.Backup
{
public class Startup : BaseStartup
{
public override string[] LogParams { get => new string[] { "ASC.Data.Backup" }; }
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) : base(configuration, hostEnvironment)
{

View File

@ -37,12 +37,13 @@ namespace ASC.Data.Backup.Storage
{
[Scope]
public class BackupRepository : IBackupRepository
{
private BackupsContext BackupContext { get; }
{
private Lazy<BackupsContext> LazyBackupsContext { get; }
private BackupsContext BackupContext { get => LazyBackupsContext.Value; }
public BackupRepository(DbContextManager<BackupsContext> backupContext)
{
BackupContext = backupContext.Value;
LazyBackupsContext = new Lazy<BackupsContext>(() => backupContext.Value);
}
public void SaveBackupRecord(BackupRecord backup)

View File

@ -63,7 +63,8 @@ namespace ASC.Data.Backup.Tasks
private bool Dump { get; set; }
private TenantManager TenantManager { get; set; }
private TempStream TempStream { get; }
private BackupsContext BackupRecordContext { get; set; }
private Lazy<BackupsContext> LazyBackupsContext { get; }
private BackupsContext BackupRecordContext { get => LazyBackupsContext.Value; }
public BackupPortalTask(DbFactory dbFactory, DbContextManager<BackupsContext> dbContextManager, IOptionsMonitor<ILog> options, TenantManager tenantManager, CoreBaseSettings coreBaseSettings, StorageFactory storageFactory, StorageFactoryConfig storageFactoryConfig, ModuleProvider moduleProvider, TempStream tempStream)
: base(dbFactory, options, storageFactory, storageFactoryConfig, moduleProvider)
@ -71,7 +72,7 @@ namespace ASC.Data.Backup.Tasks
Dump = coreBaseSettings.Standalone;
TenantManager = tenantManager;
TempStream = tempStream;
BackupRecordContext = dbContextManager.Get(DbFactory.ConnectionStringSettings.ConnectionString);
LazyBackupsContext = new Lazy<BackupsContext>(() => dbContextManager.Get(DbFactory.ConnectionStringSettings.ConnectionString));
}
public void Init(int tenantId, string fromConfigPath, string toFilePath, int limit)

View File

@ -34,8 +34,6 @@ namespace ASC.Data.Storage.Encryption
{
public class Startup : BaseStartup
{
public override string[] LogParams { get => new string[] { "ASC.Data.Storage.Encryption" }; }
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) : base(configuration, hostEnvironment)
{

View File

@ -6,7 +6,6 @@ using ASC.Api.Core;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using Autofac;
@ -64,7 +63,6 @@ namespace ASC.Data.Storage.Migration
{
services.AddMemoryCache();
var diHelper = new DIHelper(services);
LogNLogExtension.ConfigureLog(diHelper, "ASC.Data.Storage.Migration", "ASC.Migration");
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCache<>));
diHelper.RegisterProducts(hostContext.Configuration, hostContext.HostingEnvironment.ContentRootPath);

View File

@ -92,8 +92,9 @@ namespace ASC.ElasticSearch
private TenantManager TenantManager { get; }
private BaseIndexerHelper BaseIndexerHelper { get; }
private Settings Settings { get; }
private IServiceProvider ServiceProvider { get; }
private WebstudioDbContext WebstudioDbContext { get; }
private IServiceProvider ServiceProvider { get; }
private Lazy<WebstudioDbContext> LazyWebstudioDbContext { get; }
private WebstudioDbContext WebstudioDbContext { get => LazyWebstudioDbContext.Value; }
public BaseIndexer(
Client client,
@ -110,7 +111,7 @@ namespace ASC.ElasticSearch
BaseIndexerHelper = baseIndexerHelper;
Settings = settings;
ServiceProvider = serviceProvider;
WebstudioDbContext = dbContextManager.Value;
LazyWebstudioDbContext = new Lazy<WebstudioDbContext>(() => dbContextManager.Value);
}
internal void Index(T data, bool immediately = true)

View File

@ -34,8 +34,6 @@ using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.ElasticSearch.Service;
using Autofac;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
@ -49,7 +47,6 @@ namespace ASC.ElasticSearch
private ICacheNotify<AscCacheItem> Notify { get; }
private ICacheNotify<IndexAction> IndexNotify { get; }
private IServiceProvider ServiceProvider { get; }
public ILifetimeScope Container { get; }
private bool IsStarted { get; set; }
private CancellationTokenSource CancellationTokenSource { get; set; }
private Timer Timer { get; set; }
@ -60,14 +57,12 @@ namespace ASC.ElasticSearch
ICacheNotify<AscCacheItem> notify,
ICacheNotify<IndexAction> indexNotify,
IServiceProvider serviceProvider,
ILifetimeScope container,
Settings settings)
{
Log = options.Get("ASC.Indexer");
Notify = notify;
IndexNotify = indexNotify;
ServiceProvider = serviceProvider;
Container = container;
CancellationTokenSource = new CancellationTokenSource();
Period = TimeSpan.FromMinutes(settings.Period.Value);
}
@ -137,13 +132,19 @@ namespace ASC.ElasticSearch
Timer.Change(Timeout.Infinite, Timeout.Infinite);
IsStarted = true;
using var scope = Container.BeginLifetimeScope();
var wrappers = scope.Resolve<IEnumerable<IFactoryIndexer>>();
Parallel.ForEach(wrappers, w =>
using (var scope = ServiceProvider.CreateScope())
{
IndexProduct(w, reindex);
});
var wrappers = scope.ServiceProvider.GetService<IEnumerable<IFactoryIndexer>>();
Parallel.ForEach(wrappers, wrapper =>
{
using (var scope = ServiceProvider.CreateScope())
{
var w = (IFactoryIndexer)scope.ServiceProvider.GetService(wrapper.GetType());
IndexProduct(w, reindex);
}
});
}
Timer.Change(Period, Period);
IndexNotify.Publish(new IndexAction() { Indexing = "", LastIndexed = DateTime.Now.Ticks }, CacheNotifyAction.Any);

View File

@ -64,18 +64,15 @@ namespace ASC.Feed.Aggregator
private ConfigurationExtension Configuration { get; }
private IServiceProvider ServiceProvider { get; }
public ILifetimeScope Container { get; }
public FeedAggregatorService(
ConfigurationExtension configuration,
IServiceProvider serviceProvider,
ILifetimeScope container,
IOptionsMonitor<ILog> optionsMonitor,
IOptionsSnapshot<SignalrServiceClient> optionsSnapshot)
{
Configuration = configuration;
ServiceProvider = serviceProvider;
Container = container;
Log = optionsMonitor.Get("ASC.Feed.Agregator");
SignalrServiceClient = optionsSnapshot.Get("counters");
}
@ -129,8 +126,7 @@ namespace ASC.Feed.Aggregator
Log.DebugFormat("Start of collecting feeds...");
var unreadUsers = new Dictionary<int, Dictionary<Guid, int>>();
using var autofacScope = Container.BeginLifetimeScope();
var modules = autofacScope.Resolve<IEnumerable<IFeedModule>>();
var modules = scope.ServiceProvider.GetService<IEnumerable<IFeedModule>>();
foreach (var module in modules)
{

View File

@ -6,7 +6,6 @@ using ASC.Api.Core;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core.Notify.Senders;
using ASC.Notify.Config;
@ -67,7 +66,6 @@ namespace ASC.Notify
services.AddMemoryCache();
var diHelper = new DIHelper(services);
LogNLogExtension.ConfigureLog(diHelper, "ASC.Notify", "ASC.Notify.Messages");
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCache<>));
diHelper.RegisterProducts(hostContext.Configuration, hostContext.HostingEnvironment.ContentRootPath);

View File

@ -0,0 +1,42 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<ApplicationIcon />
<OutputType>Exe</OutputType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ASC.Api.Core\ASC.Api.Core.csproj" />
<ProjectReference Include="..\..\ASC.Common\ASC.Common.csproj" />
<ProjectReference Include="..\..\ASC.Core.Common\ASC.Core.Common.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="radicale.log.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties properties_4launchsettings_1json__JsonSchema="https://json.schemastore.org/local.settings.json" /></VisualStudio></ProjectExtensions>
</Project>

View File

@ -0,0 +1,103 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using ASC.Common.DependencyInjection;
using ASC.Common.Utils;
namespace ASC.Radicale
{
public class Program
{
public static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureAppConfiguration((hostContext, config) =>
{
var buided = config.Build();
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");
config
.AddJsonFile("appsettings.json")
.AddJsonFile("storage.json")
.AddJsonFile("kafka.json")
.AddJsonFile($"appsettings.services.json", true)
//.AddJsonFile("radicale.json")
.AddJsonFile($"kafka.{env}.json", true)
.AddJsonFile($"appsettings.{env}.json", true)
.AddJsonFile($"radicale.{env}.json", true)
.AddEnvironmentVariables()
.AddCommandLine(args)
.AddInMemoryCollection(new Dictionary<string, string>
{
{"pathToConf", path }
}
);
})
.ConfigureServices((hostContext, services) =>
{
services.AddMemoryCache();
var diHelper = new DIHelper(services);
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCache<>));
diHelper.RegisterProducts(hostContext.Configuration, hostContext.HostingEnvironment.ContentRootPath);
services.AddHostedService<RadicaleServiceLauncher>();
diHelper.TryAdd<RadicaleServiceLauncher>();
})
.ConfigureContainer<ContainerBuilder>((context, builder) =>
{
builder.Register(context.Configuration, false, false);
});
}
}

View File

@ -0,0 +1,29 @@
{
"profiles": {
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "radicale",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5024",
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "radicale",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5024",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"distributionName": "Ubuntu-20.04"
}
}
}

View File

@ -0,0 +1,129 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
namespace ASC.Radicale
{
[Scope]
public class RadicaleServiceLauncher : IHostedService
{
private Process Proc { get; set; }
private ProcessStartInfo StartInfo { get; set; }
private ILog Logger { get; set; }
//private ConfigurationExtension ConfigurationExtension { get; }
//private IHostEnvironment HostEnvironment { get; set; }
public RadicaleServiceLauncher(
IOptionsMonitor<ILog> options,
ConfigurationExtension configurationExtension,
IHostEnvironment hostEnvironment)
{
Logger = options.CurrentValue;
//ConfigurationExtension = configurationExtension;
//HostEnvironment = hostEnvironment;
}
public Task StartAsync(CancellationToken cancellationToken)
{
try
{
var pythonName = "python";
var configPath = Path.GetFullPath(CrossPlatform.PathCombine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "radicale.config"));
if (WorkContext.IsMono)
{
pythonName = "python3";
}
StartInfo = new ProcessStartInfo
{
CreateNoWindow = false,
UseShellExecute = false,
FileName = pythonName,
WindowStyle = ProcessWindowStyle.Hidden,
Arguments = $"-m radicale --config \"{configPath}\"",
WorkingDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)
};
StartRedicale();
}
catch (Exception e)
{
Logger.Error(e);
}
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
StopRadicale();
return Task.CompletedTask;
}
private void StartRedicale()
{
StopRadicale();
Proc = Process.Start(StartInfo);
}
private void StopRadicale()
{
try
{
if (Proc != null && !Proc.HasExited)
{
Proc.Kill();
if (!Proc.WaitForExit(10000))
{
Logger.Warn("The process does not wait for completion.");
}
Proc.Close();
Proc.Dispose();
Proc = null;
}
}
catch (Exception e)
{
Logger.Error("Radicale failed stop", e);
}
}
}
}

View File

@ -0,0 +1,3 @@
{
"pathToConf": "..\\..\\..\\config"
}

View File

@ -0,0 +1,124 @@
# -*- mode: conf -*-
# vim:ft=cfg
# Config file for Radicale - A simple calendar server
#
# Place it into /etc/radicale/config (global)
# or ~/.config/radicale/config (user)
#
# The current values are the default ones
[server]
# CalDAV server hostnames separated by a comma
# IPv4 syntax: address:port
# IPv6 syntax: [address]:port
# For example: 0.0.0.0:9999, [::]:9999
hosts = localhost:5232
# Max parallel connections
#max_connections = 8
# Max size of request body (bytes)
#max_content_length = 100000000
# Socket timeout (seconds)
#timeout = 30
# SSL flag, enable HTTPS protocol
#ssl = False
# SSL certificate path
#certificate = /etc/ssl/radicale.cert.pem
# SSL private key
#key = /etc/ssl/radicale.key.pem
# CA certificate for validating clients. This can be used to secure
# TCP traffic between Radicale and a reverse proxy
#certificate_authority =
[encoding]
# Encoding for responding requests
#request = utf-8
# Encoding for storing local collections
#stock = utf-8
[auth]
# Authentication method
# Value: none | htpasswd | remote_user | http_x_remote_user
type = app_auth_plugin
portal_url = http://localhost/apisystem/caldav
machine_key = 1123askdasjklasbnd
# Htpasswd filename
#htpasswd_filename = /etc/radicale/users
# Htpasswd encryption method
# Value: plain | bcrypt | md5
# bcrypt requires the installation of radicale[bcrypt].
#htpasswd_encryption = md5
# Incorrect authentication delay (seconds)
#delay = 1
# Message displayed in the client when a password is needed
#realm = Radicale - Password Required
[rights]
# Rights backend
# Value: none | authenticated | owner_only | owner_write | from_file
type = app_rights_plugin
# File for rights management from_file
file = radicale.rights
[storage]
# Storage backend
# Value: multifilesystem
# type = multifilesystem
type = app_store_plugin
portal_url = http://localhost/apisystem/caldav
# Folder for storing local collections, created if not present
filesystem_folder = ..\..\Data\radicale\collections\
# Delete sync token that are older (seconds)
#max_sync_token_age = 2592000
# Command that is run after changes to storage
# Example: ([ -d .git ] || git init) && git add -A && (git diff --cached --quiet || git commit -m "Changes by "%(user)s)
#hook =
[web]
# Web interface backend
# Value: none | internal
type = none
[logging]
# Threshold for the logger
# Value: debug | info | warning | error | critical
level = info
# Don't include passwords in logs
#mask_passwords = True
[headers]
# Additional HTTP headers
Access-Control-Allow-Origin = *

View File

@ -0,0 +1,22 @@
[loggers]
keys = root
[handlers]
keys = file
[formatters]
keys = full
[logger_root]
# Change this to DEBUG or INFO for higher verbosity.
level = WARNING
handlers = file
[handler_file]
class = handlers.TimedRotatingFileHandler
# Specify the output file here.
args = ('../../../../../../Logs/radicale.log','midnight', 1, 7)
formatter = full
[formatter_full]
format = %(asctime)s - [%(thread)x] %(levelname)s: %(message)s

View File

@ -0,0 +1,14 @@
[admin]
user: admin@ascsystem@.+
collection: .*
permissions: RWrw
[allow-shared-read]
user: .+
collection: %(user)s/.+-shared$
permissions: Rr
[owner-write]
user: .+
collection: %(user)s.*$
permissions: RWrw

View File

@ -32,7 +32,6 @@ using ASC.Api.Core;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using Autofac;
@ -93,8 +92,7 @@ namespace ASC.Socket.IO.Svc
var diHelper = new DIHelper(services);
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCache<>));
diHelper.RegisterProducts(hostContext.Configuration, hostContext.HostingEnvironment.ContentRootPath);
LogNLogExtension.ConfigureLog(diHelper, "ASC.Socket.IO.Svc");
services.AddHostedService<SocketServiceLauncher>();
diHelper.TryAdd<SocketServiceLauncher>();
})

View File

@ -32,7 +32,6 @@ using ASC.Api.Core;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.SsoAuth.Svc;
@ -94,8 +93,7 @@ namespace ASC.Socket.IO.Svc
var diHelper = new DIHelper(services);
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCache<>));
diHelper.RegisterProducts(hostContext.Configuration, hostContext.HostingEnvironment.ContentRootPath);
LogNLogExtension.ConfigureLog(diHelper, "ASC.SsoAuth.Svc");
services.AddHostedService<Launcher>();
diHelper.TryAdd<Launcher>();
})

View File

@ -6,7 +6,6 @@ using ASC.Api.Core;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core.Notify;
using ASC.Notify;
@ -69,7 +68,6 @@ namespace ASC.Studio.Notify
var diHelper = new DIHelper(services);
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCache<>));
diHelper.RegisterProducts(hostContext.Configuration, hostContext.HostingEnvironment.ContentRootPath);
LogNLogExtension.ConfigureLog(diHelper, "ASC.Notify", "ASC.Notify.Messages");
services.AddHostedService<ServiceLauncher>();
diHelper.TryAdd<ServiceLauncher>();
NotifyConfigurationExtension.Register(diHelper);

View File

@ -34,8 +34,6 @@ namespace ASC.TelegramService
{
public class Startup : BaseStartup
{
public override string[] LogParams { get => new string[] { "ASC.TelegramService" }; }
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) : base(configuration, hostEnvironment)
{

View File

@ -32,7 +32,6 @@ using ASC.Api.Core;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using Autofac;
@ -92,8 +91,7 @@ namespace ASC.Thumbnails.Svc
services.AddMemoryCache();
var diHelper = new DIHelper(services);
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCache<>));
LogNLogExtension.ConfigureLog(diHelper, "ASC.Thumbnails.Svc");
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCache<>));
services.AddHostedService<ThumbnailsServiceLauncher>();
diHelper.TryAdd<ThumbnailsServiceLauncher>();
})

View File

@ -31,7 +31,6 @@ using System.Threading.Tasks;
using ASC.Api.Core;
using ASC.Common;
using ASC.Common.DependencyInjection;
using ASC.Common.Logging;
using ASC.Common.Utils;
using Autofac;
@ -93,8 +92,7 @@ namespace ASC.UrlShortener.Svc
services.AddMemoryCache();
var diHelper = new DIHelper(services);
LogNLogExtension.ConfigureLog(diHelper, "ASC.UrlShortener.Svc");
services.AddHostedService<UrlShortenerServiceLauncher>();
diHelper.TryAdd<UrlShortenerServiceLauncher>();
})

View File

@ -45,6 +45,7 @@
"enabled": "enabled"
},
"version": {
"number": "1.0.0",
"release": {
"date": "",
"sign": ""

View File

@ -52,7 +52,7 @@
"type": "ASC.Web.Core.IWebItem, ASC.Web.Core"
}
],
"instanceScope": "InstancePerLifetimeScope"
"instanceScope": "InstancePerLifetimeScope"
}
]
}

View File

@ -22,6 +22,11 @@ map $request_uri $header_x_frame_options {
default "SAMEORIGIN";
}
map $request_uri $cache_control {
default "";
~*^/(api\/2\.0.*|storage|login\.ashx|products\/.+\/httphandlers\/filehandler\.ashx|ChunkedUploader.ashx|apisystem|sh) "no-cache, no-store, must-revalidate";
}
include /etc/nginx/includes/onlyoffice-*.conf;
server {
@ -29,6 +34,8 @@ server {
add_header Access-Control-Allow-Origin *;
add_header X-Frame-Options $header_x_frame_options;
add_header Cache-Control $cache_control;
etag on;
large_client_header_buffers 4 16k;
@ -74,10 +81,9 @@ server {
}
location / {
proxy_pass http://localhost:5001;
expires 365d;
location ~* /(manifest.json|service-worker.js|appIcon.png|bg-error.png) {
expires 365d;
location ~* /(manifest.json|sw.js|appIcon.png|bg-error.png) {
root $public_root;
try_files /$basename /index.html =404;
}
@ -88,24 +94,26 @@ server {
}
location ~* /static/images/ {
expires 365d;
root $public_root;
try_files /images/$basename /index.html =404;
}
location ~* /static/fonts/ {
expires 365d;
root $public_root;
try_files /fonts/$basename /index.html =404;
}
location ~* /static/offline/ {
expires 365d;
root $public_root;
try_files /offline/$basename /index.html =404;
}
location ~* /thirdparty/ {
expires 365d;
root $public_root;
try_files /thirdparty/third-party.html /index.html =404;
}
location ~* /static/locales/(?<content>[^/]+) {
expires 365d;
root $public_root;
try_files /locales/$content/$basename /index.html =404;
}
@ -113,12 +121,10 @@ server {
location /login {
#rewrite login/(.*) /$1 break;
expires 365d;
proxy_pass http://localhost:5011;
}
location /sockjs-node {
expires 365d;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
@ -133,26 +139,22 @@ server {
}
location /api/2.0 {
expires -1;
add_header Cache-Control $cache_control;
location ~* /(files|encryption|privacyroom) {
expires -1;
proxy_pass http://localhost:5007;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location ~* /(people|group) {
expires -1;
proxy_pass http://localhost:5004;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location ~* /(authentication|modules|portal|security|settings|smtpsettings|capabilities|thirdparty) {
expires -1;
proxy_pass http://localhost:5000;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
location ~* portal/(.*)(backup|restore)(.*) {
expires -1;
rewrite (.*)/portal/(.*) $1/backup/$2 break;
proxy_redirect off;
@ -163,44 +165,39 @@ server {
}
location ~* /backup {
expires -1;
proxy_pass http://localhost:5012;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location ~* /project {
expires -1;
proxy_pass http://localhost:5020;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location ~* /crm {
expires -1;
proxy_pass http://localhost:5021;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location ~* /mail {
expires -1;
proxy_pass http://localhost:5022;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location ~* /calendar {
expires -1;
proxy_pass http://localhost:5023;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
}
location /storage {
expires -1;
add_header Cache-Control $cache_control;
proxy_pass http://localhost:5003;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location /login.ashx {
expires -1;
add_header Cache-Control $cache_control;
proxy_pass http://localhost:5003;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
@ -209,12 +206,10 @@ server {
location /products {
location ~* /people {
#rewrite products/people/(.*) /$1 break;
expires 365d;
proxy_pass http://localhost:5002;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
location ~* /(sockjs-node) {
expires 365d;
rewrite products/people(.*)/(sockjs-node)/(.*) /$2/$3 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
@ -231,7 +226,6 @@ server {
location ~* /(manifest.json|service-worker.js|appIcon.png|bg-error.png) {
expires 365d;
root $public_root;
try_files /$basename /index.html =404;
}
@ -239,7 +233,6 @@ server {
location ~* /files/doceditor {
#rewrite products/files/doceditor/(.*) /$1 break;
expires 365d;
proxy_pass http://localhost:5013;
proxy_redirect off;
proxy_set_header Host $host;
@ -253,12 +246,10 @@ server {
location ~* /files {
#rewrite products/files/(.*) /$1 break;
expires 365d;
proxy_pass http://localhost:5008;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
location ~* /sockjs-node {
expires 365d;
rewrite products/files(.*)/sockjs-node/(.*) /$2/$3 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
@ -273,13 +264,12 @@ server {
}
location ~* /(manifest.json|service-worker.js|appIcon.png|bg-error.png) {
expires 365d;
root $public_root;
try_files /$basename /index.html =404;
}
location ~* (/httphandlers/filehandler.ashx|ChunkedUploader.ashx) {
expires -1;
add_header Cache-Control $cache_control;
proxy_pass http://localhost:5007;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
@ -287,12 +277,10 @@ server {
location ~* /crm {
#rewrite products/crm/(.*) /$1 break;
expires 365d;
proxy_pass http://localhost:5014;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
location ~* /sockjs-node {
expires 365d;
rewrite products/crm(.*)/sockjs-node/(.*) /$2/$3 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
@ -308,13 +296,12 @@ server {
}
location ~* /(manifest.json|service-worker.js|appIcon.png|bg-error.png) {
expires 365d;
root $public_root;
try_files /$basename /index.html =404;
}
location ~* (/httphandlers/filehandler.ashx|ChunkedUploader.ashx) {
expires -1;
add_header Cache-Control $cache_control;
proxy_pass http://localhost:5007;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
@ -322,12 +309,10 @@ server {
location ~* /projects {
#rewrite products/projects/(.*) /$1 break;
expires 365d;
proxy_pass http://localhost:5015;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
location ~* /sockjs-node {
expires 365d;
rewrite products/projects(.*)/sockjs-node/(.*) /$2/$3 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
@ -343,13 +328,12 @@ server {
}
location ~* /(manifest.json|service-worker.js|appIcon.png|bg-error.png) {
expires 365d;
root $public_root;
try_files /$basename /index.html =404;
}
location ~* (/httphandlers/filehandler.ashx|ChunkedUploader.ashx) {
expires -1;
add_header Cache-Control $cache_control;
proxy_pass http://localhost:5007;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
@ -357,12 +341,10 @@ server {
location ~* /mail {
#rewrite products/mail/(.*) /$1 break;
expires 365d;
proxy_pass http://localhost:5016;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
location ~* /sockjs-node {
expires 365d;
rewrite products/projects(.*)/sockjs-node/(.*) /$2/$3 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
@ -378,13 +360,12 @@ server {
}
location ~* /(manifest.json|service-worker.js|appIcon.png|bg-error.png) {
expires 365d;
root $public_root;
try_files /$basename /index.html =404;
}
location ~* (/httphandlers/filehandler.ashx|ChunkedUploader.ashx) {
expires -1;
add_header Cache-Control $cache_control;
proxy_pass http://localhost:5007;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
@ -392,12 +373,10 @@ server {
location ~* /calendar {
#rewrite products/calendar/(.*) /$1 break;
expires 365d;
proxy_pass http://localhost:5017;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
location ~* /sockjs-node {
expires 365d;
rewrite products/projects(.*)/sockjs-node/(.*) /$2/$3 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
@ -413,13 +392,12 @@ server {
}
location ~* /(manifest.json|service-worker.js|appIcon.png|bg-error.png) {
expires 365d;
root $public_root;
try_files /$basename /index.html =404;
}
location ~* (/httphandlers/filehandler.ashx|ChunkedUploader.ashx) {
expires -1;
add_header Cache-Control $cache_control;
proxy_pass http://localhost:5007;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
@ -427,16 +405,23 @@ server {
}
location /apisystem {
expires -1;
add_header Cache-Control $cache_control;
rewrite apisystem/(.*) /$1 break;
proxy_pass http://localhost:5010;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location /sh {
expires -1;
add_header Cache-Control $cache_control;
rewrite sh/(.*) /$1 break;
proxy_pass http://localhost:9999;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
}
location /caldav {
rewrite caldav/(.*) /$1 break;
proxy_pass http://localhost:5232;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
}

9
config/workbox-config.js Normal file
View File

@ -0,0 +1,9 @@
module.exports = {
globDirectory: 'build/deploy/',
globPatterns: [
"**/*.{js,css}"
],
globIgnores: ['**/remoteEntry.js'],
swSrc: 'packages/asc-web-common/utils/sw-template.js',
swDest: 'build/deploy/public/sw.js'
};

View File

@ -0,0 +1,11 @@
module.exports = {
globDirectory: 'build/deploy/',
globPatterns: [
'**/*.{ico,woff2,svg,html,json,js,png}'
],
ignoreURLParametersMatching: [
/^utm_/,
/^fbclid$/
],
swDest: 'build/deploy/public/sw.js'
};

View File

@ -1,5 +1,5 @@
{
"version": "0.1.10",
"version": "1.0.0",
"npmClient": "yarn",
"packages": [
"packages/asc-web-components",

View File

@ -18,6 +18,19 @@
"scripts": {
"wipe": "rimraf node_modules yarn.lock web/**/node_modules products/**/node_modules",
"build": "concurrently \"wsrun --parallel build\"",
"sw-build": "workbox injectManifest config/workbox-config.js && yarn sw-modify && yarn sw-minimize",
"sw-calendar-replace": "replace-in-files --string='products/ASC.Calendar/client/' --replacement='products/calendar/' build/deploy/public/sw.js",
"sw-crm-replace": "replace-in-files --string='products/ASC.CRM/client/' --replacement='products/crm/' build/deploy/public/sw.js",
"sw-files-replace": "replace-in-files --string='products/ASC.Files/client/' --replacement='products/files/' build/deploy/public/sw.js",
"sw-files-editor-replace": "replace-in-files --string='products/ASC.Files/editor/' --replacement='products/files/doceditor/' build/deploy/public/sw.js",
"sw-mail-replace": "replace-in-files --string='products/ASC.Mail/client/' --replacement='products/mail/' build/deploy/public/sw.js",
"sw-people-replace": "replace-in-files --string='products/ASC.People/client/' --replacement='products/people/' build/deploy/public/sw.js",
"sw-projects-replace": "replace-in-files --string='products/ASC.Projects/client/' --replacement='products/projects/' build/deploy/public/sw.js",
"sw-studio-replace": "replace-in-files --string='studio/client/' --replacement='/' build/deploy/public/sw.js",
"sw-studio-login-replace": "replace-in-files --string='studio/login/' --replacement='login/' build/deploy/public/sw.js",
"sw-public-replace": "replace-in-files --string='public/' --replacement='static/' build/deploy/public/sw.js",
"sw-modify": "yarn sw-calendar-replace && yarn sw-crm-replace && yarn sw-crm-replace && yarn sw-files-replace && yarn sw-files-editor-replace && yarn sw-mail-replace && yarn sw-people-replace && yarn sw-projects-replace && yarn sw-studio-replace && yarn sw-studio-login-replace && yarn sw-public-replace",
"sw-minimize": "yarn terser --compress --mangle -- build/deploy/public/sw.js --output build/deploy/public/sw.js",
"start": "concurrently \"wsrun --parallel start\"",
"start-prod": "concurrently \"wsrun --parallel start-prod\"",
"serve": "concurrently \"wsrun --parallel serve\"",
@ -26,12 +39,15 @@
"storybook": "yarn workspace @appserver/components storybook",
"storybook-build": "yarn workspace @appserver/components run storybook-build",
"bump": "lerna version --no-push --no-git-tag-version",
"deploy": "rimraf build/deploy && concurrently \"wsrun --parallel deploy\""
"deploy": "rimraf build/deploy && concurrently \"wsrun --parallel deploy\" && cp -r public build/deploy && yarn sw-build"
},
"devDependencies": {
"lerna": "^3.22.1",
"concurrently": "^5.3.0",
"wsrun": "^5.2.4",
"rimraf": "^3.0.2"
"lerna": "^3.22.1",
"replace-in-files-cli": "^1.0.0",
"rimraf": "^3.0.2",
"terser": "^5.7.1",
"workbox-cli": "^6.1.5",
"wsrun": "^5.2.4"
}
}

View File

@ -364,7 +364,14 @@ class PageLayout extends React.Component {
{isSectionFilterAvailable && (
<>
<div id="main-bar" style={{ display: "grid" }}></div>
<div
id="main-bar"
style={{
display: "grid",
paddingRight: "20px",
paddingTop: "10px",
}}
></div>
<SubSectionFilter className="section-header_filter">
{sectionFilterContent
? sectionFilterContent.props.children

View File

@ -5,76 +5,70 @@ $font-family-base: "Open Sans", sans-serif;
font-family: "Open Sans";
font-weight: 300;
font-style: normal;
src: url("../../public/fonts/light/open-sans-light.woff2") format("woff2");
src: url("/static/fonts/open-sans-light.woff2") format("woff2");
}
@font-face {
font-family: "Open Sans";
font-weight: 300;
font-style: italic;
src: url("../../public/fonts/light-italic/open-sans-light-italic.woff2")
format("woff2");
src: url("/static/fonts/open-sans-light-italic.woff2") format("woff2");
}
@font-face {
font-family: "Open Sans";
font-weight: normal;
font-style: normal;
src: url("../../public/fonts/regular/open-sans-regular.woff2") format("woff2");
src: url("/static/fonts/open-sans-regular.woff2") format("woff2");
}
@font-face {
font-family: "Open Sans";
font-weight: normal;
font-style: italic;
src: url("../../public/fonts/italic/open-sans-italic.woff2") format("woff2");
src: url("/static/fonts/open-sans-italic.woff2") format("woff2");
}
@font-face {
font-family: "Open Sans";
font-weight: 600;
font-style: normal;
src: url("../../public/fonts/semibold/open-sans-semibold.woff2")
format("woff2");
src: url("/static/fonts/open-sans-semibold.woff2") format("woff2");
}
@font-face {
font-family: "Open Sans";
font-weight: 600;
font-style: italic;
src: url("../../public/fonts/semibold-italic/open-sans-semibold-italic.woff2")
format("woff2");
src: url("/static/fonts/open-sans-semibold-italic.woff2") format("woff2");
}
@font-face {
font-family: "Open Sans";
font-weight: bold;
font-style: normal;
src: url("../../public/fonts/bold/open-sans-bold.woff2") format("woff2");
src: url("/static/fonts/open-sans-bold.woff2") format("woff2");
}
@font-face {
font-family: "Open Sans";
font-weight: bold;
font-style: italic;
src: url("../../public/fonts/bold-italic/open-sans-bold-italic.woff2")
format("woff2");
src: url("/static/fonts/open-sans-bold-italic.woff2") format("woff2");
}
@font-face {
font-family: "Open Sans";
font-weight: 800;
font-style: normal;
src: url("../../public/fonts/extra-bold/open-sans-extra-bold.woff2")
format("woff2");
src: url("/static/fonts/open-sans-extra-bold.woff2") format("woff2");
}
@font-face {
font-family: "Open Sans";
font-weight: 800;
font-style: italic;
src: url("../../public/fonts/extra-bold-italic/open-sans-extra-bold-italic.woff2")
format("woff2");
src: url("/static/fonts/open-sans-extra-bold-italic.woff2") format("woff2");
}
html,
@ -115,3 +109,12 @@ body.desktop {
-o-user-select: none;
mozuserselect: none;
}
#snackbar {
display: flex;
justify-content: center;
position: fixed;
width: calc(100vw - 60px);
padding: 30px;
bottom: 15px;
}

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/common",
"version": "0.1.10",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "echo 'skip it'",
@ -18,6 +18,7 @@
},
"dependencies": {
"global": "^4.4.0",
"react-selecto": "^1.12.0"
"react-selecto": "^1.12.0",
"workbox-window": "^6.1.5"
}
}

View File

@ -82,6 +82,7 @@ class SettingsStore {
appId: "",
measurementId: "",
};
version = "";
constructor() {
makeAutoObservable(this);

View File

@ -1,8 +1,60 @@
import { Workbox } from "workbox-window";
import React from "react";
import ReactDOM from "react-dom";
export function registerSW(homepage) {
import { Workbox } from "workbox-window";
import SnackBar from "@appserver/components/snackbar";
import i18n from "i18next";
import { useTranslation, initReactI18next } from "react-i18next";
import Backend from "i18next-http-backend";
import { LANGUAGE } from "../constants";
import { loadLanguagePath } from "./";
i18n
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
fallbackLng: "en",
load: "all",
//debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
format: function (value, format) {
if (format === "lowercase") return value.toLowerCase();
return value;
},
},
backend: {
loadPath: loadLanguagePath(""),
},
react: {
useSuspense: false,
},
});
const SnackBarWrapper = (props) => {
const { t, ready } = useTranslation("Common", { i18n });
if (ready) {
const barConfig = {
parentElementId: "snackbar",
text: t("NewVersionAvailable"),
btnText: t("Load"),
onAction: () => props.onButtonClick(),
opacity: 1,
};
return <SnackBar {...barConfig} />;
}
return <></>;
};
const registerSW = () => {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
const wb = new Workbox(`${homepage}/sw.js`);
const wb = new Workbox(`/sw.js`);
//TODO: watch https://developers.google.com/web/tools/workbox/guides/advanced-recipes and https://github.com/webmaxru/prog-web-news/blob/5ff94b45c9d317409c21c0fbb7d76e92f064471b/src/app/app-shell/app-shell.component.ts
@ -12,16 +64,34 @@ export function registerSW(homepage) {
`until all tabs running the current version have fully unloaded.`
);
// Assuming the user accepted the update, set up a listener
// that will reload the page as soon as the previously waiting
// service worker has taken control.
wb.addEventListener("controlling", () => {
window.location.reload();
});
try {
const snackbarNode = document.createElement("div");
snackbarNode.id = "snackbar";
document.body.appendChild(snackbarNode);
// This will postMessage() to the waiting service worker.
wb.messageSkipWaiting();
ReactDOM.render(
<SnackBarWrapper
onButtonClick={() => {
snackbarNode.remove();
wb.addEventListener("controlling", () => {
window.location.reload();
});
wb.messageSkipWaiting();
}}
/>,
document.getElementById("snackbar")
);
} catch (e) {
console.error("showSkipWaitingPrompt", e);
wb.addEventListener("controlling", () => {
window.location.reload();
});
// This will postMessage() to the waiting service worker.
wb.messageSkipWaiting();
}
// let snackBarRef = this.snackBar.open(
// "A new version of the website available",
@ -58,4 +128,10 @@ export function registerSW(homepage) {
} else {
console.log("SKIP registerSW because of DEV mode");
}
}
};
window.SW = {
registerSW: registerSW,
};
export { registerSW };

View File

@ -1,48 +1,36 @@
import {
precacheAndRoute,
cleanupOutdatedCaches,
//createHandlerBoundToURL,
} from "workbox-precaching";
import { setCacheNameDetails } from "workbox-core";
import { clientsClaim } from "workbox-core";
import { /*NavigationRoute,*/ registerRoute } from "workbox-routing";
import { googleFontsCache, imageCache, offlineFallback } from "workbox-recipes";
import {
//CacheFirst,
//NetworkFirst,
StaleWhileRevalidate,
} from "workbox-strategies";
//import { ExpirationPlugin } from "workbox-expiration";
//import { BroadcastUpdatePlugin } from "workbox-broadcast-update";
importScripts(
"https://storage.googleapis.com/workbox-cdn/releases/6.1.5/workbox-sw.js"
);
workbox.setConfig({
debug: false,
});
// This will trigger the importScripts() for workbox.strategies and its dependencies:
const { precacheAndRoute, cleanupOutdatedCaches } = workbox.precaching;
const { setCacheNameDetails, clientsClaim } = workbox.core;
const { registerRoute } = workbox.routing;
const { googleFontsCache, imageCache, offlineFallback } = workbox.recipes;
const { StaleWhileRevalidate } = workbox.strategies;
// SETTINGS
// Claiming control to start runtime caching asap
clientsClaim();
// Use to update the app after user triggered refresh (without prompt)
//self.skipWaiting();
// PRECACHING
// Setting custom cache name
setCacheNameDetails({ precache: "wb6-precache", runtime: "wb6-runtime" });
// We inject manifest here using "workbox-build" in workbox-inject.js
precacheAndRoute(self.__WB_MANIFEST);
const precachRoutes = self.__WB_MANIFEST;
precacheAndRoute(precachRoutes);
// Remove cache from the previous WB versions
cleanupOutdatedCaches();
// NAVIGATION ROUTING
// This assumes /index.html has been precached.
// const navHandler = createHandlerBoundToURL("/index.html");
// const navigationRoute = new NavigationRoute(navHandler, {
// denylist: [new RegExp("/out-of-spa/")], // Also might be specified explicitly via allowlist
// });
// registerRoute(navigationRoute);
// STATIC RESOURCES
googleFontsCache({ cachePrefix: "wb6-gfonts" });
@ -77,24 +65,3 @@ offlineFallback({
imageFallback: "/static/offline/offline.svg",
fontFallback: false,
});
// ALL OTHER EVENTS
// Receive push and show a notification
// self.addEventListener("push", function (event) {
// console.log("[Service Worker]: Received push event", event);
// var notificationData = {};
// if (event.data.json()) {
// notificationData = event.data.json();
// } else {
// notificationData = {
// title: "Something Has Happened",
// message: "Something you might want to check out",
// icon: "/assets/img/pwa-logo.png",
// };
// }
// self.registration.showNotification(notificationData.title, notificationData);
// });

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/components",
"version": "0.1.10",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "echo 'skip it'",

View File

@ -1,217 +1,140 @@
import "./snackbar.css";
import React from "react";
import ReactDOM from "react-dom";
import PropType from "prop-types";
import StyledSnackBar from "./styled-snackbar";
import StyledCrossIcon from "./styled-snackbar-action";
import StyledLogoIcon from "./styled-snackbar-logo";
import Box from "../box";
import Heading from "../heading";
import Text from "../text";
export const Snackbar = {
current: null,
snackbar: null,
show(params) {
let options = extend(true, defaultConfig, params);
class SnackBar extends React.Component {
static show(barConfig) {
const { parentElementId, ...rest } = barConfig;
if (Snackbar.current) {
Snackbar.current.style.opacity = 0;
setTimeout(
function () {
let parent = this.parentElement;
if (parent)
// possible null if too many/fast snackbars
parent.removeChild(this);
}.bind(Snackbar.current),
500
);
let parentElementNode =
parentElementId && document.getElementById(parentElementId);
if (!parentElementNode) {
const snackbarNode = document.createElement("div");
snackbarNode.id = "snackbar";
document.body.appendChild(snackbarNode);
parentElementNode = snackbarNode;
}
Snackbar.snackbar = document.createElement("div");
Snackbar.snackbar.className = `snackbar-container ${
options.parentElementId && "inline"
} ${options.customClass}`;
Snackbar.snackbar.style.width = options.width;
window.snackbar = barConfig;
if (options.logoImg) {
let logoImg = document.createElement("div");
logoImg.src = options.logoImg;
logoImg.className = "logo";
logoImg.alt = "logo";
logoImg.innerHTML = `<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15ZM7 6V4H9V6H7ZM7 12V7H9V12H7Z" fill="black"/>
</svg>`;
Snackbar.snackbar.appendChild(logoImg);
}
let textContainer = document.createElement("div");
textContainer.className = "text-container";
Snackbar.snackbar.appendChild(textContainer);
if (options.textHeader) {
let header = document.createElement("p");
header.style.margin = 0;
header.style.padding = 0;
header.style.color = options.textColor;
header.style.fontSize = "12px";
header.style.fontWeight = 600;
header.style.lineHeight = "16px";
header.innerHTML = options.textHeader;
textContainer.appendChild(header);
}
let body = document.createElement("p");
body.style.margin = 0;
body.style.padding = 0;
body.style.color = options.textColor;
body.style.fontSize = "12px";
body.style.lineHeight = "16px";
body.innerHTML = options.textBody;
textContainer.appendChild(body);
Snackbar.snackbar.appendChild(textContainer);
Snackbar.snackbar.style.background = options.backgroundColor;
if (options.showSecondButton) {
let secondButton = document.createElement("button");
secondButton.className = "action";
secondButton.innerHTML = options.secondButtonText;
secondButton.style.color = options.secondButtonTextColor;
secondButton.addEventListener("click", () => {
options.onSecondButtonClick(Snackbar.snackbar);
});
Snackbar.snackbar.appendChild(secondButton);
}
if (options.showAction) {
let actionButton = document.createElement("button");
actionButton.className = "action";
if (options.actionIcon) {
actionButton.innerHTML = `<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.76288 6.35869C7.56764 6.16343 7.56764 5.84687 7.76288 5.65161L10.9493 2.46498C11.1445 2.26973 11.1445 1.95316 10.9493 1.75791L10.2422 1.05077C10.0469 0.855489 9.73031 0.855489 9.53504 1.05077L6.34878 4.23729C6.15352 4.43257 5.83691 4.43257 5.64165 4.23729L2.46017 1.05556C2.26491 0.860275 1.9483 0.860275 1.75304 1.05556L1.04596 1.76269C0.850716 1.95795 0.850716 2.27451 1.04596 2.46977L4.22755 5.65161C4.42279 5.84687 4.42279 6.16343 4.22755 6.35869L1.0501 9.53639C0.854858 9.73165 0.854858 10.0482 1.0501 10.2435L1.75718 10.9506C1.95245 11.1459 2.26905 11.1459 2.46432 10.9506L5.64165 7.77302C5.83691 7.57774 6.15352 7.57774 6.34878 7.77302L9.5309 10.9554C9.72616 11.1507 10.0428 11.1507 10.238 10.9554L10.9451 10.2483C11.1404 10.053 11.1404 9.73644 10.9451 9.54118L7.76288 6.35869Z" fill="#999976"/>
</svg>`; //`<img src="${options.actionIcon}" alt="${options.actionText}" class="action-icon">`;
} else {
actionButton.innerHTML = options.actionText;
actionButton.style.color = options.actionTextColor;
}
actionButton.addEventListener("click", function () {
options.onActionClick(Snackbar.snackbar);
});
Snackbar.snackbar.appendChild(actionButton);
}
if (options.duration) {
setTimeout(
function () {
if (Snackbar.current === this) {
Snackbar.current.style.opacity = 0;
// When natural remove event occurs let's move the snackbar to its origins
Snackbar.current.style.top = "-100px";
Snackbar.current.style.bottom = "-100px";
}
}.bind(Snackbar.snackbar),
options.duration
);
}
Snackbar.snackbar.addEventListener(
"transitionend",
function (event) {
if (event.propertyName === "opacity" && this.style.opacity === "0") {
if (typeof options.onClose === "function") options.onClose(this);
this.parentElement.removeChild(this);
if (Snackbar.current === this) {
Snackbar.current = null;
}
}
}.bind(Snackbar.snackbar)
);
Snackbar.current = Snackbar.snackbar;
var parentElm =
options.parentElementId &&
document.getElementById(options.parentElementId);
if (parentElm) {
parentElm.appendChild(Snackbar.snackbar);
} else {
document.body.appendChild(Snackbar.snackbar);
}
//let bottom = getComputedStyle(Snackbar.snackbar).bottom;
//let top = getComputedStyle(Snackbar.snackbar).top;
Snackbar.snackbar.style.opacity = 1;
Snackbar.snackbar.className = `snackbar-container ${
options.parentElementId && "inline"
} ${options.customClass} ${
!options.parentElementId && ` snackbar-pos ${options.position}`
}`;
},
close() {
if (Snackbar.current) {
Snackbar.current.style.opacity = 0;
}
},
};
const defaultConfig = {
parentElementId: null,
backgroundColor: "#F8F7BF",
textColor: "#000",
width: "auto",
textHeader: null,
textBody: "Default Body text",
logoImg: "/static/images/info.react.svg",
showAction: false,
actionIcon: "/static/images/cross.react.svg",
actionText: "Close",
actionTextColor: "#0F4071",
showSecondButton: false,
secondButtonText: "Reload",
secondButtonTextColor: "#0F4071",
position: "bottom-center",
duration: null,
customClass: "",
onActionClick: (element) => {
element.style.opacity = 0;
},
onSecondButtonClick: () => {
location.reload();
},
onClose: () => {},
};
const extend = function () {
let extended = {};
let deep = false;
let i = 0;
let length = arguments.length;
if (Object.prototype.toString.call(arguments[0]) === "[object Boolean]") {
deep = arguments[0];
i++;
ReactDOM.render(<SnackBar {...rest} />, parentElementNode);
}
const merge = function (obj) {
for (let prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
if (
deep &&
Object.prototype.toString.call(obj[prop]) === "[object Object]"
) {
extended[prop] = extend(true, extended[prop], obj[prop]);
} else {
extended[prop] = obj[prop];
}
}
static close() {
if (window.snackbar && window.snackbar.parentElementId) {
const bar = document.querySelector(`#${window.snackbar.parentElementId}`);
bar.remove();
//ReactDOM.unmountComponentAtNode(window.snackbar.parentElementId);
} else {
console.error("Not found snackbar");
}
}
onActionClick = (e) => {
this.props.onAction && this.props.onAction(e);
};
for (; i < length; i++) {
let obj = arguments[i];
merge(obj);
}
render() {
const {
text,
headerText,
btnText,
textColor,
showIcon,
fontSize,
fontWeight,
textAlign,
htmlContent,
...rest
} = this.props;
return extended;
const headerStyles = headerText ? {} : { display: "none" };
return (
<StyledSnackBar {...rest}>
{htmlContent ? (
<div
dangerouslySetInnerHTML={{
__html: htmlContent,
}}
/>
) : (
<>
{showIcon && (
<Box className="logo">
<StyledLogoIcon size="medium" color={textColor} />
</Box>
)}
<Box className="text-container" textAlign={textAlign}>
<Heading
size="xsmall"
isInline={true}
className="text-header"
style={headerStyles}
color={textColor}
>
{headerText}
</Heading>
<div className="text-body" textAlign={textAlign}>
<Text
as="p"
color={textColor}
fontSize={fontSize}
fontWeight={fontWeight}
>
{text}
</Text>
{btnText && (
<button className="button" onClick={this.onActionClick}>
<Text color={textColor}>{btnText}</Text>
</button>
)}
</div>
</Box>
</>
)}
{!btnText && (
<button className="action" onClick={this.onActionClick}>
<StyledCrossIcon size="medium" />
</button>
)}
)
</StyledSnackBar>
);
}
}
SnackBar.propTypes = {
text: PropType.string,
headerText: PropType.string,
btnText: PropType.string,
backgroundImg: PropType.string,
backgroundColor: PropType.string,
textColor: PropType.string,
showIcon: PropType.bool,
onAction: PropType.func,
fontSize: PropType.string,
fontWeight: PropType.string,
textAlign: PropType.string,
htmlContent: PropType.string,
};
SnackBar.defaultProps = {
backgroundColor: "#f8f7bf",
textColor: "#000",
showIcon: true,
fontSize: "13px",
fontWeight: "400",
textAlign: "left",
htmlContent: "",
};
export default SnackBar;

View File

@ -1,125 +0,0 @@
.snackbar-container {
transition: all 500ms ease;
transition-property: top, right, bottom, left, opacity;
font-family: Open Sans, sans-serif, Arial;
font-size: 12px;
min-height: 14px;
position: fixed;
display: flex;
justify-content: space-between;
align-items: flex-start;
color: white;
line-height: 16px;
padding: 12px;
bottom: -100px;
top: -100px;
opacity: 0;
z-index: 9999;
}
.snackbar-container.inline {
position: relative;
z-index: initial;
top: initial;
bottom: initial;
margin: 16px 24px 0 0;
max-width: initial;
justify-content: initial;
}
.snackbar-container.inline button:last-child {
margin-left: auto;
padding-left: 8px;
}
.snackbar-container .action {
background: inherit;
display: inline-block;
border: none;
font-size: inherit;
color: #4caf50;
margin: 0 0 0 24px;
padding: 0;
min-width: min-content;
cursor: pointer;
}
.logo {
padding-right: 10px;
}
.text-container {
display: flex;
flex-direction: column;
gap: 5px;
}
@media (min-width: 640px) {
.snackbar-container {
min-width: 400px;
max-width: 568px;
display: inline-flex;
border-radius: 6px;
margin: 24px;
}
}
@media (max-width: 640px) {
.snackbar-container {
left: 0;
right: 0;
width: 100%;
}
}
@media (max-width: 769px) {
.snackbar-container.inline {
margin: 16px 0px 0 0;
}
}
.snackbar-pos.bottom-center {
top: auto !important;
bottom: 0;
left: 50%;
transform: translate(-50%, 0);
}
.snackbar-pos.bottom-left {
top: auto !important;
bottom: 0;
left: 0;
}
.snackbar-pos.bottom-right {
top: auto !important;
bottom: 0;
right: 0;
}
.snackbar-pos.top-left {
bottom: auto !important;
top: 0;
left: 0;
}
.snackbar-pos.top-center {
bottom: auto !important;
top: 0;
left: 50%;
transform: translate(-50%, 0);
}
.snackbar-pos.top-right {
bottom: auto !important;
top: 0;
right: 0;
}
@media (max-width: 640px) {
.snackbar-pos.bottom-center,
.snackbar-pos.top-center {
left: 0;
transform: none;
}
}

View File

@ -0,0 +1,51 @@
import React from "react";
import Box from "../box";
import SnackBar from "./";
export default {
title: "Components/SnackBar",
component: SnackBar,
parameters: {
docs: {
description: {
component: "SnackBar is used for displaying important messages.",
},
},
},
argTypes: {
onAction: {
action: "onAction",
},
textColor: { control: "color" },
backgroundColor: { control: "color" },
showIcon: { control: "boolean" },
},
};
const Wrapper = ({ children }) => (
<Box id="main-bar" displayProp="grid">
{children}
</Box>
);
const BaseTemplate = (args) => (
<Wrapper>
<SnackBar {...args} onClose={(e) => alert("OnClose handled!", e)} />
</Wrapper>
);
export const base = BaseTemplate.bind({});
base.args = {
backgroundImg: "",
backgroundColor: "#f8f7bf",
textColor: "#000",
opacity: 1,
headerText: "Attention",
text:
"We apologize for any short-term technical issues in service functioning, that may appear on 22.06.2021 during the update of Onlyoffice Personal.",
showIcon: true,
fontSize: "13px",
fontWeight: "400",
textAlign: "left",
htmlContent: "",
};

View File

@ -0,0 +1,13 @@
import styled from "styled-components";
import CrossIcon from "../../../public/images/cross.react.svg";
import commonIconsStyles from "../utils/common-icons-style";
const StyledCrossIcon = styled(CrossIcon)`
${commonIconsStyles}
path {
fill: #999976;
}
`;
export default StyledCrossIcon;

View File

@ -0,0 +1,13 @@
import styled from "styled-components";
import InfoIcon from "../../../public/images/info.react.svg";
import commonIconsStyles from "../utils/common-icons-style";
const StyledLogoIcon = styled(InfoIcon)`
${commonIconsStyles}
path {
fill: ${(props) => props.color};
}
`;
export default StyledLogoIcon;

View File

@ -0,0 +1,73 @@
import styled from "styled-components";
import Box from "../box";
const StyledSnackBar = styled(Box)`
transition: all 500ms ease;
transition-property: top, right, bottom, left, opacity;
font-family: Open Sans, sans-serif, Arial;
font-size: 12px;
min-height: 14px;
position: relative;
display: flex;
align-items: flex-start;
color: white;
line-height: 16px;
padding: 12px;
margin: 0 0 8px 0;
opacity: ${(props) => props.opacity || 0};
width: 100%;
background-color: ${(props) => props.backgroundColor};
background-image: url(${(props) => props.backgroundImg || ""});
border-radius: 6px;
.logo {
padding-right: 10px;
}
.text-container {
width: 100%;
display: flex;
flex-direction: column;
gap: 5px;
text-align: ${(props) => props.textAlign};
.text-header {
margin: 0;
}
.text-body {
width: 100%;
display: flex;
flex-direction: row;
gap: 10px;
justify-content: ${(props) => props.textAlign};
}
}
.action {
background: inherit;
display: inline-block;
border: none;
font-size: inherit;
color: "#000";
margin: 0 0 0 24px;
padding: 0;
min-width: min-content;
cursor: pointer;
margin-left: auto;
padding-left: 8px;
text-decoration: underline;
}
.button {
background: inherit;
border: none;
font-size: 13px;
color: "#000";
cursor: pointer;
line-height: 12px;
text-decoration: underline;
}
`;
export default StyledSnackBar;

View File

@ -1,22 +1,20 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Common.DependencyInjection;
using ASC.Common.Utils;
using ASC.ElasticSearch;
using ASC.Web.CRM.Core.Search;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ASC.Common.DependencyInjection;
namespace ASC.CRM.BackgroundTasks
@ -73,9 +71,6 @@ namespace ASC.CRM.BackgroundTasks
services.AddHostedService<ServiceLauncher>();
diHelper.TryAdd<ServiceLauncher>();
LogNLogExtension.ConfigureLog(diHelper, "ASC.Files", "ASC.Feed.Agregator");
diHelper.TryAdd<FactoryIndexerCase>();
diHelper.TryAdd<FactoryIndexerContact>();
diHelper.TryAdd<FactoryIndexerContactInfo>();

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/crm",
"version": "0.1.10",
"version": "1.0.0",
"homepage": "/products/crm",
"title": "ONLYOFFICE",
"id": "6743007c-6f95-4d20-8c88-a8601ce5e76d",
@ -24,6 +24,7 @@
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^7.0.0",
"css-loader": "^3.6.0",
"external-remotes-plugin": "^1.0.0",
"file-loader": "^6.2.0",
"html-webpack-plugin": "4.5.0",
"json-loader": "^0.5.7",
@ -35,8 +36,7 @@
"terser-webpack-plugin": "^5.1.1",
"webpack": "5.14.0",
"webpack-cli": "4.5.0",
"webpack-dev-server": "3.11.2",
"workbox-webpack-plugin": "^6.1.1"
"webpack-dev-server": "3.11.2"
},
"dependencies": {
"@babel/runtime": "^7.12.5",

View File

@ -1,9 +1,8 @@
import App from "./App";
import React from "react";
import ReactDOM from "react-dom";
import config from "../package.json";
import { registerSW } from "@appserver/common/utils/sw-helper";
ReactDOM.render(<App />, document.getElementById("root"));
registerSW(config.homepage);
registerSW();

View File

@ -3,8 +3,8 @@ const CopyPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack").container
.ModuleFederationPlugin;
const ExternalTemplateRemotesPlugin = require("external-remotes-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const { InjectManifest } = require("workbox-webpack-plugin");
const combineUrl = require("@appserver/common/utils/combineUrl");
const AppServerConfig = require("@appserver/common/constants/AppServerConfig");
@ -91,17 +91,6 @@ var config = {
],
},
{ test: /\.json$/, loader: "json-loader" },
{
test: /\.(woff(2)?)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: "file-loader",
options: {
name: "fonts/[hash].[ext]",
},
},
],
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
@ -165,6 +154,7 @@ var config = {
},
},
}),
new ExternalTemplateRemotesPlugin(),
new HtmlWebpackPlugin({
template: "./public/index.html",
publicPath: homepage,
@ -194,14 +184,6 @@ module.exports = (env, argv) => {
minimize: true,
minimizer: [new TerserPlugin()],
};
config.plugins.push(
new InjectManifest({
mode: "production", //"development",
swSrc: "@appserver/common/utils/sw-template.js", // this is your sw template file
swDest: "sw.js", // this will be created in the build step
exclude: [/\.map$/, /manifest$/, /service-worker\.js$/],
})
);
} else {
config.devtool = "cheap-module-source-map";
}

View File

@ -136,11 +136,6 @@ namespace ASC.CRM.ApiModels
Data = "support@onlyoffice.com",
InfoType = ContactInfoType.Email
};
}
public void Mapping(Profile profile)
{
profile.CreateMap<ContactInfo, ContactInfoDto>();
}
}
}
}

View File

@ -374,6 +374,7 @@ namespace ASC.CRM.ApiModels
protected ListItemDto(ListItem listItem)
{
Id = listItem.ID;
Title = listItem.Title;
Description = listItem.Description;
Color = listItem.Color;

View File

@ -78,7 +78,10 @@ namespace ASC.CRM.Api
SharingOptions = new SharingOptions();
// SharingOptions.PublicItems.Add(new SharingOptions.PublicItem { Id = userId, IsGroup = false });
}
public override List<ITodo> LoadTodos(Guid userId, DateTime utcStartDate, DateTime utcEndDate)
{
return new List<ITodo>();
}
public override List<IEvent> LoadEvents(Guid userId, DateTime startDate, DateTime endDate)
{
var events = new List<IEvent>();

View File

@ -31,7 +31,7 @@ using System.Linq;
using ASC.Common;
using ASC.Common.Web;
using ASC.Core;
using ASC.Core.Common.EF;
using ASC.Core.Common.EF;
using ASC.CRM.Resources;
using ASC.Files.Core.EF;
using ASC.Web.Core;
@ -44,8 +44,10 @@ namespace ASC.Web.CRM.Configuration
[Scope]
public class CrmSpaceUsageStatManager : SpaceUsageStatManager
{
private int _tenantId;
private FilesDbContext _filesDbContext;
private int _tenantId;
private Lazy<FilesDbContext> LazyFilesDbContext { get; }
private FilesDbContext _filesDbContext { get => LazyFilesDbContext.Value; }
private PathProvider _pathProvider;
public CrmSpaceUsageStatManager(DbContextManager<FilesDbContext> filesDbContext,
@ -53,7 +55,7 @@ namespace ASC.Web.CRM.Configuration
TenantManager tenantManager)
{
_pathProvider = pathProvider;
_filesDbContext = filesDbContext.Value;
LazyFilesDbContext = new Lazy<FilesDbContext>(() => filesDbContext.Value);
_tenantId = tenantManager.GetCurrentTenant().TenantId;
}

View File

@ -45,8 +45,11 @@ namespace ASC.CRM.Core.Dao
{
public class AbstractDao
{
protected readonly List<EntityType> _supportedEntityType = new List<EntityType>();
public CrmDbContext CrmDbContext { get; }
protected readonly List<EntityType> _supportedEntityType = new List<EntityType>();
private Lazy<CrmDbContext> LazyCrmDbContext { get; }
public CrmDbContext CrmDbContext { get => LazyCrmDbContext.Value; }
protected readonly SecurityContext _securityContext;
protected readonly ICache _cache;
protected ILog _logger;
@ -66,7 +69,7 @@ namespace ASC.CRM.Core.Dao
_cache = ascCache;
CrmDbContext = dbContextManager.Get(CrmConstants.DatabaseId);
LazyCrmDbContext = new Lazy<CrmDbContext>(() => dbContextManager.Get(CrmConstants.DatabaseId));
TenantID = tenantManager.GetCurrentTenant().TenantId;
_securityContext = securityContext;

View File

@ -390,7 +390,7 @@ namespace ASC.CRM.Core.Dao
if (result > 0)
{
_cache.Insert(cacheKey, result, TimeSpan.FromSeconds(30));
_cache.Insert(cacheKey, result.ToString(), TimeSpan.FromSeconds(30));
}
return result;

View File

@ -326,7 +326,7 @@ namespace ASC.CRM.Core.Dao
}
if (result > 0)
{
_cache.Insert(cacheKey, result, TimeSpan.FromMinutes(1));
_cache.Insert(cacheKey, result.ToString(), TimeSpan.FromMinutes(1));
}
return result;

View File

@ -544,7 +544,7 @@ namespace ASC.CRM.Core.Dao
}
if (result > 0)
{
_cache.Insert(cacheKey, result, TimeSpan.FromSeconds(30));
_cache.Insert(cacheKey, result.ToString(), TimeSpan.FromSeconds(30));
}
return result;

View File

@ -397,7 +397,7 @@ namespace ASC.CRM.Core.Dao
if (result > 0)
{
_cache.Insert(cacheKey, result, TimeSpan.FromSeconds(30));
_cache.Insert(cacheKey, result.ToString(), TimeSpan.FromSeconds(30));
}
return result;
}

View File

@ -232,7 +232,7 @@ namespace ASC.CRM.Core.Dao
if (result > 0)
{
_cache.Insert(cacheKey, result, TimeSpan.FromSeconds(30));
_cache.Insert(cacheKey, result.ToString(), TimeSpan.FromSeconds(30));
}
return result;
}

View File

@ -73,13 +73,11 @@ namespace ASC.CRM.Core.Dao
private CurrencyInfo _defaultCurrency;
private TenantUtil _tenantUtil;
private DaoFactory _daoFactory;
private UserDbContext _userDbContext;
private DisplayUserSettingsHelper _displayUserSettings;
#region Constructor
public ReportDao(DbContextManager<CrmDbContext> dbContextManager,
DbContextManager<UserDbContext> dbUserContextManager,
TenantManager tenantManager,
SecurityContext securityContext,
FilesIntegration filesIntegration,
@ -112,8 +110,6 @@ namespace ASC.CRM.Core.Dao
var crmSettings = settingsManager.Load<CrmSettings>();
_userDbContext = dbUserContextManager.Get(CrmConstants.DatabaseId);
_defaultCurrency = currencyProvider.Get(crmSettings.DefaultCurrency);
_displayUserSettings = displayUserSettingsHelper;
@ -313,7 +309,7 @@ namespace ASC.CRM.Core.Dao
var file = _daoFactory.GetFileDao().SaveFile(document, stream);
SaveFile((int)file.ID, -1);
SaveFile(file.ID, -1);
result.Add(file);
}

View File

@ -52,10 +52,12 @@ namespace ASC.CRM.Core.Dao
[Scope]
public class TaskDao : AbstractDao
{
private readonly UserDbContext _userDbContext;
private readonly FactoryIndexerTask _factoryIndexer;
private readonly TenantUtil _tenantUtil;
private readonly CrmSecurity _crmSecurity;
private Lazy<UserDbContext> LazyUserDbContext { get; }
private UserDbContext _userDbContext { get => LazyUserDbContext.Value; }
public TaskDao(DbContextManager<CrmDbContext> dbContextManager,
TenantManager tenantManager,
@ -77,7 +79,7 @@ namespace ASC.CRM.Core.Dao
_crmSecurity = crmSecurity;
_tenantUtil = tenantUtil;
_factoryIndexer = factoryIndexer;
_userDbContext = userDbContext.Value;
LazyUserDbContext = new Lazy<UserDbContext>(() => userDbContext.Value);
_mapper = mapper;
}
@ -510,7 +512,7 @@ namespace ASC.CRM.Core.Dao
if (result > 0)
{
_cache.Insert(cacheKey, result, TimeSpan.FromMinutes(1));
_cache.Insert(cacheKey, result.ToString(), TimeSpan.FromMinutes(1));
}
return result;

View File

@ -27,10 +27,13 @@
using System;
using ASC.Common.Mapping;
using ASC.CRM.ApiModels;
using ASC.CRM.Classes;
using ASC.CRM.Core.EF;
using ASC.CRM.Core.Enums;
using AutoMapper;
namespace ASC.CRM.Core
{
public class ContactInfo : DomainObject, IMapFrom<DbContactInfo>
@ -78,5 +81,12 @@ namespace ASC.CRM.Core
return typeof(ContactInfoBaseCategory);
}
}
public void Mapping(Profile profile)
{
profile.CreateMap<DbContactInfo, ContactInfo>()
.ForMember(x => x.InfoType, opt => opt.MapFrom(x => x.Type));
}
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/calendar",
"version": "0.1.10",
"version": "1.0.0",
"homepage": "/products/calendar",
"id": "32d24cb5-7ece-4606-9c94-19216ba42086",
"title": "ONLYOFFICE",
@ -24,6 +24,7 @@
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^7.0.0",
"css-loader": "^3.6.0",
"external-remotes-plugin": "^1.0.0",
"file-loader": "^6.2.0",
"html-webpack-plugin": "4.5.0",
"json-loader": "^0.5.7",
@ -35,8 +36,7 @@
"terser-webpack-plugin": "^5.1.1",
"webpack": "5.14.0",
"webpack-cli": "4.5.0",
"webpack-dev-server": "3.11.2",
"workbox-webpack-plugin": "^6.1.1"
"webpack-dev-server": "3.11.2"
},
"dependencies": {
"@babel/runtime": "^7.12.5",

View File

@ -1,9 +1,8 @@
import App from "./App";
import React from "react";
import ReactDOM from "react-dom";
import config from "../package.json";
import { registerSW } from "@appserver/common/utils/sw-helper";
ReactDOM.render(<App />, document.getElementById("root"));
registerSW(config.homepage);
registerSW();

View File

@ -3,8 +3,8 @@ const CopyPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack").container
.ModuleFederationPlugin;
const ExternalTemplateRemotesPlugin = require("external-remotes-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const { InjectManifest } = require("workbox-webpack-plugin");
const combineUrl = require("@appserver/common/utils/combineUrl");
const AppServerConfig = require("@appserver/common/constants/AppServerConfig");
@ -91,17 +91,6 @@ var config = {
],
},
{ test: /\.json$/, loader: "json-loader" },
{
test: /\.(woff(2)?)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: "file-loader",
options: {
name: "fonts/[hash].[ext]",
},
},
],
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
@ -165,6 +154,7 @@ var config = {
},
},
}),
new ExternalTemplateRemotesPlugin(),
new HtmlWebpackPlugin({
template: "./public/index.html",
publicPath: homepage,
@ -194,14 +184,6 @@ module.exports = (env, argv) => {
minimize: true,
minimizer: [new TerserPlugin()],
};
config.plugins.push(
new InjectManifest({
mode: "production", //"development",
swSrc: "@appserver/common/utils/sw-template.js", // this is your sw template file
swDest: "sw.js", // this will be created in the build step
exclude: [/\.map$/, /manifest$/, /service-worker\.js$/],
})
);
} else {
config.devtool = "cheap-module-source-map";
}

232
products/ASC.Calendar/Server/.gitignore vendored Normal file
View File

@ -0,0 +1,232 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
bin/
Bin/
obj/
Obj/
# Visual Studio 2015 cache/options directory
.vs/
/wwwroot/dist/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Microsoft Azure ApplicationInsights config file
ApplicationInsights.config
# Windows Store app package directory
AppPackages/
BundleArtifacts/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
orleans.codegen.cs
/node_modules
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
# FAKE - F# Make
.fake/

View File

@ -6,25 +6,56 @@
<GenerateMvcApplicationPartsAssemblyAttributes>false</GenerateMvcApplicationPartsAssemblyAttributes>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
<NoWarn>1701;1702;NU1701</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ical.Net" Version="4.1.11" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.5" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\ASC.Api.Core\ASC.Api.Core.csproj" />
<ProjectReference Include="..\..\..\common\ASC.Data.Reassigns\ASC.Data.Reassigns.csproj" />
<ProjectReference Include="..\..\..\common\ASC.MessagingSystem\ASC.MessagingSystem.csproj" />
<ProjectReference Include="..\..\..\web\ASC.Web.Core\ASC.Web.Core.csproj" />
</ItemGroup>
<ItemGroup>
<Service Include="{7BCED72B-1DDE-4732-8EB3-2CF7002D7305}" />
</ItemGroup>
<ItemGroup>
<Compile Update="Resources\CalendarAddonResource.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>CalendarAddonResource.resx</DependentUpon>
</Compile>
<Compile Update="Resources\CalendarResource.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>CalendarResource.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources\CalendarResource.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>CalendarResource.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="Resources\CalendarResource.ru.resx">
<DependentUpon>CalendarResource.resx</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Update="Resources\CalendarAddonResource.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>CalendarAddonResource.Designer.cs</LastGenOutput>
@ -45,5 +76,8 @@
<DependentUpon>CalendarAddonResource.resx</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Folder Include="Core\Dao\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,42 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Action = ASC.Common.Security.Authorizing.Action;
namespace ASC.Calendar
{
public class CalendarAccessRights
{
public static readonly Action FullAccessAction = new Action(
new Guid("{0d68b142-e20a-446e-a832-0d6b0b65a164}"),
"Full Access", false, false);
}
}

View File

@ -0,0 +1,242 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using ASC.Core;
using ASC.Api.Core;
using ASC.Common.Security;
using ASC.Common.Security.Authorizing;
using ASC.Web.Core.Calendars;
using ASC.Calendar.Models;
using System.Net;
using System.IO;
using ASC.Calendar.iCalParser;
using ASC.Common.Utils;
namespace ASC.Calendar.BusinessObjects
{
public static class CalendarExtention
{
public static bool IsiCalStream(this BaseCalendar calendar)
{
return (calendar is BusinessObjects.Calendar && !String.IsNullOrEmpty((calendar as BusinessObjects.Calendar).iCalUrl));
}
public static bool IsExistTodo(this BaseCalendar calendar)
{
return (calendar is BusinessObjects.Calendar && (calendar as BusinessObjects.Calendar).IsTodo != 0);
}
public static BaseCalendar GetUserCalendar(this BaseCalendar calendar, UserViewSettings userViewSettings)
{
var cal = (BaseCalendar)calendar.Clone();
if (userViewSettings == null)
return cal;
//name
if (!String.IsNullOrEmpty(userViewSettings.Name))
cal.Name = userViewSettings.Name;
//backgroundColor
if (!String.IsNullOrEmpty(userViewSettings.BackgroundColor))
cal.Context.HtmlBackgroundColor = userViewSettings.BackgroundColor;
//textColor
if (!String.IsNullOrEmpty(userViewSettings.TextColor))
cal.Context.HtmlTextColor = userViewSettings.TextColor;
//TimeZoneInfo
if (userViewSettings.TimeZone != null)
cal.TimeZone = userViewSettings.TimeZone;
//alert type
cal.EventAlertType = userViewSettings.EventAlertType;
return cal;
}
public static List<EventWrapper> GetEventWrappers(this BaseCalendar calendar, Guid userId, ApiDateTime startDate, ApiDateTime endDate, EventWrapperHelper eventWrapperHelper)
{new List<EventWrapper>();
var result = new List<EventWrapper>();
if (calendar != null)
{
var events = calendar.LoadEvents(userId, startDate.UtcTime, endDate.UtcTime);
foreach (var e in events)
{
var wrapper = eventWrapperHelper.Get(e, userId, calendar.TimeZone);
var listWrapper = eventWrapperHelper.GetList(startDate.UtcTime, endDate.UtcTime, userId, e);
result.AddRange(listWrapper);
}
}
return result;
}
public static List<TodoWrapper> GetTodoWrappers(this BaseCalendar calendar, Guid userId, ApiDateTime startDate, ApiDateTime endDate, TodoWrapperHelper todoWrapperHelper)
{
var result = new List<TodoWrapper>();
if (calendar != null)
{
var events = calendar.LoadTodos(userId, startDate.UtcTime, endDate.UtcTime);
foreach (var e in events)
{
var wrapper = todoWrapperHelper.Get(e, userId, calendar.TimeZone);
result.Add(wrapper);
}
}
return result;
}
}
[DataContract(Name = "calendar", Namespace = "")]
public class Calendar : BaseCalendar, ISecurityObject
{
public static string DefaultTextColor { get { return "#000000"; } }
public static string DefaultBackgroundColor { get { return "#9bb845"; } }
public static string DefaultTodoBackgroundColor { get { return "#ffb45e"; } }
public iCalendar ICalendar { get; }
public DataProvider DataProvider { get; }
public Calendar(
AuthContext context,
TimeZoneConverter timeZoneConverter,
iCalendar iCalendar,
DataProvider dataProvider)
: base(context, timeZoneConverter)
{
ICalendar = iCalendar;
DataProvider = dataProvider;
this.ViewSettings = new List<UserViewSettings>();
this.Context.CanChangeAlertType = true;
this.Context.CanChangeTimeZone = true;
}
public int TenantId { get; set; }
public List<UserViewSettings> ViewSettings { get; set; }
public string iCalUrl { get; set; }
public string calDavGuid { get; set; }
public int IsTodo { get; set; }
#region ISecurityObjectId Members
/// <inheritdoc/>
public object SecurityId
{
get { return this.Id; }
}
/// <inheritdoc/>
public Type ObjectType
{
get { return typeof(Calendar); }
}
#endregion
#region ISecurityObjectProvider Members
public IEnumerable<ASC.Common.Security.Authorizing.IRole> GetObjectRoles(ASC.Common.Security.Authorizing.ISubject account, ISecurityObjectId objectId, SecurityCallContext callContext)
{
List<IRole> roles = new List<IRole>();
if (account.ID.Equals(this.OwnerId))
roles.Add(ASC.Common.Security.Authorizing.Constants.Owner);
return roles;
}
public ISecurityObjectId InheritFrom(ISecurityObjectId objectId)
{
throw new NotImplementedException();
}
public bool InheritSupported
{
get { return false; }
}
public bool ObjectRolesSupported
{
get { return true; }
}
#endregion
public override List<IEvent> LoadEvents(Guid userId, DateTime utcStartDate, DateTime utcEndDate)
{
if (!String.IsNullOrEmpty(iCalUrl))
{
try
{
var cal = ICalendar.GetFromUrl(iCalUrl, this.Id);
return cal.LoadEvents(userId, utcStartDate, utcEndDate);
}
catch
{
return new List<IEvent>();
}
}
return DataProvider.LoadEvents(Convert.ToInt32(this.Id), userId, TenantId, utcStartDate, utcEndDate)
.Cast<IEvent>()
.ToList();
}
public override List<ITodo> LoadTodos(Guid userId, DateTime utcStartDate, DateTime utcEndDate)
{
if (!String.IsNullOrEmpty(iCalUrl))
{
try
{
var cal = ICalendar.GetFromUrl(iCalUrl, this.Id);
return cal.LoadTodos(userId, utcStartDate, utcEndDate);
}
catch
{
return new List<ITodo>();
}
}
return DataProvider.LoadTodos(Convert.ToInt32(this.Id), userId, TenantId, utcStartDate, utcEndDate)
.Cast<ITodo>()
.ToList();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,112 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using ASC.Common.Security;
using ASC.Common.Security.Authorizing;
using ASC.Calendar.Models;
using ASC.Web.Core.Calendars;
using ASC.Core.Tenants;
using ASC.Core;
using ASC.Common.Utils;
using ASC.Calendar.iCalParser;
namespace ASC.Calendar.BusinessObjects
{
[AllDayLongUTCAttribute]
public class Event : BaseEvent, ISecurityObject
{
private AuthContext AuthContext { get; }
private TimeZoneConverter TimeZoneConverter { get; }
private iCalendar ICalendar { get; }
private DataProvider DataProvider { get; }
public Event(AuthContext context,
TimeZoneConverter timeZoneConverter,
iCalendar iCalendar,
DataProvider dataProvider)
{
AuthContext = context;
ICalendar = iCalendar;
TimeZoneConverter = timeZoneConverter;
DataProvider = dataProvider;
}
public int TenantId { get; set; }
#region ISecurityObjectId Members
public object SecurityId
{
get { return this.Id; }
}
/// <inheritdoc/>
public Type ObjectType
{
get { return typeof(Event); }
}
#endregion
#region ISecurityObjectProvider Members
public IEnumerable<ASC.Common.Security.Authorizing.IRole> GetObjectRoles(ASC.Common.Security.Authorizing.ISubject account, ISecurityObjectId objectId, SecurityCallContext callContext)
{
List<IRole> roles = new List<IRole>();
if (account.ID.Equals(this.OwnerId))
roles.Add(ASC.Common.Security.Authorizing.Constants.Owner);
return roles;
}
public ISecurityObjectId InheritFrom(ISecurityObjectId objectId)
{
int calId;
if (int.TryParse(this.CalendarId, out calId))
return new Calendar(AuthContext, TimeZoneConverter, ICalendar, DataProvider) { Id = this.CalendarId };
return null;
}
public bool InheritSupported
{
get { return true; }
}
public bool ObjectRolesSupported
{
get { return true; }
}
#endregion
}
}

View File

@ -0,0 +1,213 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using ASC.Calendar.iCalParser;
using ASC.Common;
namespace ASC.Calendar.BusinessObjects
{
[Scope]
public class EventHistory
{
public int CalendarId { get; set; }
public string EventUid { get; set; }
public int EventId { get; set; }
public string Ics { get; set; }
public List<Ical.Net.Calendar> History { get; set; }
}
[Scope]
public class EventHistoryHelper
{
public DDayICalParser DDayICalParser { get; }
public EventHistoryHelper(
DDayICalParser dDayICalParser)
{
DDayICalParser = dDayICalParser;
}
public EventHistory Get(int calendarId, string eventUid, int eventId, string ics)
{
var eventHistory = new EventHistory();
eventHistory.CalendarId = calendarId;
eventHistory.EventUid = eventUid;
eventHistory.EventId = eventId;
eventHistory.Ics = ics;
var history = DDayICalParser.DeserializeCalendar(ics);
eventHistory.History = history == null ? new List<Ical.Net.Calendar>() : history.ToList();
return eventHistory;
}
public bool Contains(Ical.Net.Calendar calendar, EventHistory eventHistory)
{
if (!eventHistory.History.Any() || calendar == null || calendar.Events == null || calendar.Events.FirstOrDefault() == null)
return false;
var eventObj = calendar.Events.First();
var isExist = eventHistory.History
.Where(x => x.Method == calendar.Method)
.Select(x => x.Events.First())
.Any(x => x.Sequence == eventObj.Sequence && DDayICalParser.ToUtc(x.DtStamp) == DDayICalParser.ToUtc(eventObj.DtStamp));
return isExist;
}
public Ical.Net.Calendar GetMerged(EventHistory eventHistory)
{
if (!eventHistory.History.Any()) return null;
var allCalendars = eventHistory.History
.Where(x => x != null && x.Events != null && x.Events.FirstOrDefault() != null)
.ToList();
if (!allCalendars.Any()) return null;
var recurrenceIdCalendars = new List<Ical.Net.Calendar>();
var calendars = new List<Ical.Net.Calendar>();
foreach (var cal in allCalendars)
{
if (cal.Events.First().RecurrenceId == null)
calendars.Add(cal);
else
recurrenceIdCalendars.Add(cal);
}
recurrenceIdCalendars = recurrenceIdCalendars
.OrderByDescending(x => x.Events.First().DtStamp)
.ToList();
if (!calendars.Any())
{
return recurrenceIdCalendars.FirstOrDefault(x => x.Method != Ical.Net.CalendarMethods.Reply) ?? recurrenceIdCalendars.First();
}
recurrenceIdCalendars = recurrenceIdCalendars
.Where(x => x.Method == Ical.Net.CalendarMethods.Cancel)
.ToList();
var sequence = calendars
.Select(x => x.Events.First())
.Max(x => x.Sequence);
calendars = calendars
.Where(x => x.Events.First().Sequence == sequence)
.OrderByDescending(x => x.Events.First().DtStamp)
.ToList();
var targetCalendar = calendars.FirstOrDefault(x => x.Method != Ical.Net.CalendarMethods.Reply) ?? calendars.First();
if (targetCalendar == null) return null;
var targetEvent = targetCalendar.Events.First();
if (targetCalendar.Method == Ical.Net.CalendarMethods.Cancel)
targetEvent.Status = Ical.Net.EventStatus.Cancelled;
calendars = calendars
.Where(x => x.Method == Ical.Net.CalendarMethods.Reply)
.OrderBy(x => x.Events.First().DtStamp)
.ToList();
foreach (var calendar in calendars)
{
var tmpEvent = calendar.Events.First();
foreach (var tmpAttendee in tmpEvent.Attendees)
{
var exist = false;
foreach (var targetAttendee in targetEvent.Attendees)
{
if (!targetAttendee.Value.OriginalString.Equals(tmpAttendee.Value.OriginalString, StringComparison.OrdinalIgnoreCase))
continue;
var parameters = new Ical.Net.ParameterList();
foreach (var param in targetAttendee.Parameters)
{
switch (param.Group)
{
case "PARTSTAT":
parameters.Add(new Ical.Net.CalendarParameter(param.Group, tmpAttendee.ParticipationStatus));
break;
case "RSVP":
parameters.Add(new Ical.Net.CalendarParameter(param.Group, tmpAttendee.Rsvp.ToString().ToUpper()));
break;
default:
parameters.Add(param);
break;
}
}
targetAttendee.Parameters.Clear();
foreach (var param in parameters)
{
targetAttendee.Parameters.Add(param);
}
targetAttendee.ParticipationStatus = tmpAttendee.ParticipationStatus;
targetAttendee.Rsvp = tmpAttendee.Rsvp;
exist = true;
break;
}
if (!exist)
targetEvent.Attendees.Add(tmpAttendee);
}
}
foreach (var recurrenceIdCalendar in recurrenceIdCalendars)
{
var removedEvent = recurrenceIdCalendar.Events.First();
if (targetEvent.ExceptionDates.All(x => !x.First().Contains(removedEvent.RecurrenceId)))
{
targetEvent.ExceptionDates.Add(new Ical.Net.DataTypes.PeriodList
{
removedEvent.RecurrenceId
});
}
}
targetCalendar.Events.Clear();
targetCalendar.Events.Add(targetEvent);
return targetCalendar;
}
}
}

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