Merge branch 'master' of https://github.com/ONLYOFFICE/CommunityServer-AspNetCore
This commit is contained in:
commit
4f0336e288
1
build/install/snap/.gitignore
vendored
Normal file
1
build/install/snap/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
!*/
|
7
build/install/snap/run.sh
Normal file
7
build/install/snap/run.sh
Normal file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
rm -dfr parts
|
||||
rm -dfr prime
|
||||
rm -dfr stage
|
||||
|
||||
#snapcraft
|
4
build/install/snap/snap/.snapcraft/state
Normal file
4
build/install/snap/snap/.snapcraft/state
Normal file
@ -0,0 +1,4 @@
|
||||
!GlobalState
|
||||
assets:
|
||||
build-packages: []
|
||||
build-snaps: []
|
Binary file not shown.
27
build/install/snap/snap/plugins/x-redis.py
Normal file
27
build/install/snap/snap/plugins/x-redis.py
Normal file
@ -0,0 +1,27 @@
|
||||
import os
|
||||
import logging
|
||||
import shutil
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
import snapcraft
|
||||
from snapcraft.plugins import make
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RedisPlugin(make.MakePlugin):
|
||||
|
||||
def build(self):
|
||||
super(make.MakePlugin, self).build()
|
||||
|
||||
command = ['make']
|
||||
|
||||
if self.options.makefile:
|
||||
command.extend(['-f', self.options.makefile])
|
||||
|
||||
if self.options.make_parameters:
|
||||
command.extend(self.options.make_parameters)
|
||||
|
||||
self.run(command + ['-j{}'.format(self.project.parallel_build_count)])
|
||||
self.run(command + ['install', 'PREFIX=' + self.installdir])
|
153
build/install/snap/snap/snapcraft.yaml
Normal file
153
build/install/snap/snap/snapcraft.yaml
Normal file
@ -0,0 +1,153 @@
|
||||
name: onlyoffice-communityserver
|
||||
version: "10.0.0"
|
||||
summary: ""
|
||||
description: ""
|
||||
grade: stable
|
||||
confinement: devmode
|
||||
|
||||
apps:
|
||||
nginx:
|
||||
command: start_nginx
|
||||
daemon: simple
|
||||
restart-condition: always
|
||||
plugs: [network, network-bind]
|
||||
mysql:
|
||||
command: start_mysql
|
||||
stop-command: support-files/mysql.server stop
|
||||
daemon: simple
|
||||
restart-condition: always
|
||||
plugs: [network, network-bind]
|
||||
mysql-client:
|
||||
command: mysql --defaults-file=$SNAP_DATA/mysql/root.ini
|
||||
plugs: [network, network-bind]
|
||||
mysqldump:
|
||||
command: mysqldump --defaults-file=$SNAP_DATA/mysql/root.ini --lock-tables onlyoffice
|
||||
plugs: [network, network-bind]
|
||||
hooks:
|
||||
configure:
|
||||
plugs: [network, network-bind]
|
||||
parts:
|
||||
python:
|
||||
plugin: python
|
||||
python-version: python3
|
||||
|
||||
node:
|
||||
plugin: nodejs
|
||||
node-engine: 12.9.1
|
||||
|
||||
nginx:
|
||||
plugin: autotools
|
||||
source: https://github.com/nginx/nginx.git
|
||||
source-type: git
|
||||
# Need the prepare step because configure script resides in an unintuitive
|
||||
# location.
|
||||
override-build: |
|
||||
cp auto/configure .
|
||||
snapcraftctl build
|
||||
build-packages:
|
||||
- libpcre3
|
||||
- libpcre3-dev
|
||||
- zlib1g-dev
|
||||
stage:
|
||||
# Remove scripts that we'll be replacing with our own
|
||||
- -conf/nginx.conf
|
||||
|
||||
nginx-customizations:
|
||||
plugin: dump
|
||||
source: src/nginx/
|
||||
|
||||
# Download the boost headers for MySQL. Note that the version used may need to
|
||||
# be updated if the version of MySQL changes.
|
||||
boost:
|
||||
plugin: dump
|
||||
source: https://github.com/kyrofa/boost_tarball/raw/master/boost_1_59_0.tar.gz
|
||||
source-checksum: sha1/5123209db194d66d69a9cfa5af8ff473d5941d97
|
||||
# When building MySQL, the headers in the source directory 'boost/' are
|
||||
# required. Previously, using the 'copy' plugin, the whole archive was put
|
||||
# under 'boost/', making the headers reside in 'boost/boost/'. Due to a bug,
|
||||
# we now only stage the 'boost/' directory without moving it.
|
||||
#
|
||||
# Bug: https://bugs.launchpad.net/snapcraft/+bug/1757093
|
||||
stage:
|
||||
- boost/
|
||||
prime:
|
||||
- -*
|
||||
|
||||
mysql:
|
||||
plugin: cmake
|
||||
source: https://github.com/mysql/mysql-server.git
|
||||
source-tag: mysql-5.7.22
|
||||
source-depth: 1
|
||||
override-pull: |
|
||||
snapcraftctl pull
|
||||
git apply $SNAPCRAFT_STAGE/support-compile-time-disabling-of-setpriority.patch
|
||||
after: [boost, patches]
|
||||
configflags:
|
||||
- -DWITH_BOOST=$SNAPCRAFT_STAGE
|
||||
- -DWITH_INNODB_PAGE_CLEANER_PRIORITY=OFF
|
||||
- -DCMAKE_INSTALL_PREFIX=/
|
||||
- -DBUILD_CONFIG=mysql_release
|
||||
- -DWITH_UNIT_TESTS=OFF
|
||||
- -DWITH_EMBEDDED_SERVER=OFF
|
||||
- -DWITH_ARCHIVE_STORAGE_ENGINE=OFF
|
||||
- -DWITH_BLACKHOLE_STORAGE_ENGINE=OFF
|
||||
- -DWITH_FEDERATED_STORAGE_ENGINE=OFF
|
||||
- -DWITH_PARTITION_STORAGE_ENGINE=OFF
|
||||
- -DINSTALL_MYSQLTESTDIR=
|
||||
build-packages:
|
||||
- wget
|
||||
- g++
|
||||
- cmake
|
||||
- bison
|
||||
- libncurses5-dev
|
||||
- libaio-dev
|
||||
stage:
|
||||
# Remove scripts that we'll be replacing with our own
|
||||
- -support-files/mysql.server
|
||||
- -COPYING
|
||||
prime:
|
||||
# Remove scripts that we'll be replacing with our own
|
||||
- -support-files/mysql.server
|
||||
|
||||
# Remove unused binaries that waste space
|
||||
- -bin/innochecksum
|
||||
- -bin/lz4_decompress
|
||||
- -bin/myisam*
|
||||
- -bin/mysqladmin
|
||||
- -bin/mysqlbinlog
|
||||
- -bin/mysql_client_test
|
||||
- -bin/mysql_config*
|
||||
- -bin/mysqld_multi
|
||||
- -bin/mysqlimport
|
||||
- -bin/mysql_install_db
|
||||
- -bin/mysql_plugin
|
||||
- -bin/mysqlpump
|
||||
- -bin/mysql_secure_installation
|
||||
- -bin/mysqlshow
|
||||
- -bin/mysqlslap
|
||||
- -bin/mysql_ssl_rsa_setup
|
||||
- -bin/mysqltest
|
||||
- -bin/mysql_tzinfo_to_sql
|
||||
- -bin/perror
|
||||
- -bin/replace
|
||||
- -bin/resolveip
|
||||
- -bin/resolve_stack_dump
|
||||
- -bin/zlib_decompress
|
||||
|
||||
# Copy over our MySQL scripts
|
||||
mysql-customizations:
|
||||
plugin: dump
|
||||
source: src/mysql/
|
||||
|
||||
patches:
|
||||
source: src/patches
|
||||
plugin: dump
|
||||
prime:
|
||||
- -*
|
||||
|
||||
|
||||
hooks:
|
||||
plugin: dump
|
||||
source: src/hooks/
|
||||
organize:
|
||||
bin/: snap/hooks/
|
10
build/install/snap/src/hooks/bin/configure
vendored
Executable file
10
build/install/snap/src/hooks/bin/configure
vendored
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
# shellcheck source=src/hooks/utilities/hook-utilities
|
||||
. "$SNAP/utilities/hook-utilities"
|
||||
|
||||
# Signal to services that the configure hook is running. Useful to ensure
|
||||
# services don't restart until the configuration transaction has completed.
|
||||
set_configure_hook_running
|
||||
trap 'set_configure_hook_not_running' EXIT
|
||||
|
32
build/install/snap/src/hooks/utilities/hook-utilities
Executable file
32
build/install/snap/src/hooks/utilities/hook-utilities
Executable file
@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
|
||||
CONFIGURE_LOCKFILE="/tmp/locks/configure-hook"
|
||||
|
||||
mkdir -p "$(dirname $CONFIGURE_LOCKFILE)"
|
||||
chmod 750 "$(dirname $CONFIGURE_LOCKFILE)"
|
||||
|
||||
configure_hook_running()
|
||||
{
|
||||
[ -f "$CONFIGURE_LOCKFILE" ]
|
||||
}
|
||||
|
||||
set_configure_hook_running()
|
||||
{
|
||||
touch "$CONFIGURE_LOCKFILE"
|
||||
}
|
||||
|
||||
set_configure_hook_not_running()
|
||||
{
|
||||
rm -f "$CONFIGURE_LOCKFILE"
|
||||
}
|
||||
|
||||
wait_for_configure_hook()
|
||||
{
|
||||
if configure_hook_running; then
|
||||
printf "Waiting for configure hook... "
|
||||
while configure_hook_running; do
|
||||
sleep 1
|
||||
done
|
||||
printf "done\n"
|
||||
fi
|
||||
}
|
97
build/install/snap/src/mysql/bin/start_mysql
Executable file
97
build/install/snap/src/mysql/bin/start_mysql
Executable file
@ -0,0 +1,97 @@
|
||||
#!/bin/sh
|
||||
|
||||
# shellcheck source=src/mysql/utilities/mysql-utilities
|
||||
. "$SNAP/utilities/mysql-utilities"
|
||||
|
||||
root_option_file="$SNAP_DATA/mysql/root.ini"
|
||||
new_install=false
|
||||
|
||||
# Make sure the database is initialized (this is safe to run if already
|
||||
# initialized)
|
||||
if mysqld --initialize-insecure --basedir="$SNAP" --datadir="$SNAP_DATA/mysql" --lc-messages-dir="$SNAP/share"; then
|
||||
new_install=true
|
||||
fi
|
||||
|
||||
set_mysql_setup_running
|
||||
|
||||
# Start mysql
|
||||
"$SNAP/support-files/mysql.server" start
|
||||
|
||||
# Initialize new installation if necessary.
|
||||
if [ $new_install = true ]; then
|
||||
# Generate a password for the root mysql user.
|
||||
printf "Generating root mysql password... "
|
||||
root_password="$(tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c64)"
|
||||
printf "done\n"
|
||||
|
||||
# Generate a password for the onlyoffice mysql user.
|
||||
printf "Generating onlyoffice mysql password... "
|
||||
onlyoffice_password="$(tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c64)"
|
||||
printf "done\n"
|
||||
|
||||
# Save root user information
|
||||
cat <<-EOF > "$root_option_file"
|
||||
[client]
|
||||
socket=$MYSQL_SOCKET
|
||||
user=root
|
||||
EOF
|
||||
chmod 600 "$root_option_file"
|
||||
|
||||
# Now set everything up in one step:
|
||||
# 1) Set the root user's password
|
||||
# 2) Create the onlyoffice user
|
||||
# 3) Create the onlyoffice database
|
||||
# 4) Grant the onlyoffice user privileges on the onlyoffice database
|
||||
printf "Setting up users and onlyoffice database... "
|
||||
if mysql --defaults-file="$root_option_file" <<-SQL
|
||||
ALTER USER 'root'@'localhost' IDENTIFIED BY '$root_password';
|
||||
CREATE USER 'onlyoffice'@'localhost' IDENTIFIED WITH mysql_native_password BY '$onlyoffice_password';
|
||||
CREATE DATABASE IF NOT EXISTS onlyoffice CHARACTER SET utf8 COLLATE 'utf8_general_ci';
|
||||
GRANT ALL PRIVILEGES ON onlyoffice.* TO 'onlyoffice'@'localhost' IDENTIFIED WITH mysql_native_password BY '$onlyoffice_password';
|
||||
SQL
|
||||
then
|
||||
printf "done\n"
|
||||
else
|
||||
echo "Failed to initialize-- reverting..."
|
||||
"$SNAP/support-files/mysql.server" stop
|
||||
rm -rf "$SNAP_DATA"/mysql/*
|
||||
fi
|
||||
|
||||
# Now the root mysql user has a password. Save that as well.
|
||||
echo "password=$root_password" >> "$root_option_file"
|
||||
else
|
||||
# Okay, this isn't a new installation. However, we recently changed
|
||||
# the location of MySQL's socket. Make sure the root
|
||||
# option file is updated to look there instead of the old location.
|
||||
sed -ri "s|(socket\s*=\s*)/var/snap/.*mysql.sock|\1$MYSQL_SOCKET|" "$root_option_file"
|
||||
fi
|
||||
|
||||
# Wait here until mysql is running
|
||||
wait_for_mysql -f
|
||||
|
||||
# Check and upgrade mysql tables if necessary. This will return 0 if the upgrade
|
||||
# succeeded, in which case we need to restart mysql.
|
||||
echo "Checking/upgrading mysql tables if necessary..."
|
||||
if mysql_upgrade --defaults-file="$root_option_file"; then
|
||||
echo "Restarting mysql server after upgrade..."
|
||||
"$SNAP/support-files/mysql.server" restart
|
||||
|
||||
# Wait for server to come back after upgrade
|
||||
wait_for_mysql -f
|
||||
fi
|
||||
|
||||
# If this was a new installation, wait until the server is all up and running
|
||||
# before saving off the onlyoffice user's password. This way the presence of the
|
||||
# file can be used as a signal that mysql is ready to be used.
|
||||
if [ $new_install = true ]; then
|
||||
mysql_set_onlyoffice_password "$onlyoffice_password"
|
||||
fi
|
||||
|
||||
set_mysql_setup_not_running
|
||||
|
||||
# Wait here until mysql exits (turn a forking service into simple). This is
|
||||
# only needed for Ubuntu Core 15.04, as 16.04 supports forking services.
|
||||
pid=$(mysql_pid)
|
||||
while kill -0 "$pid" 2>/dev/null; do
|
||||
sleep 1
|
||||
done
|
8
build/install/snap/src/mysql/my.cnf
Normal file
8
build/install/snap/src/mysql/my.cnf
Normal file
@ -0,0 +1,8 @@
|
||||
[mysqld]
|
||||
user=root
|
||||
secure-file-priv=NULL
|
||||
skip-networking
|
||||
sql_mode = 'NO_ENGINE_SUBSTITUTION'
|
||||
max_connections = 1000
|
||||
max_allowed_packet = 1048576000
|
||||
group_concat_max_len = 2048
|
BIN
build/install/snap/src/mysql/support-files/.mysql.server.swp
Normal file
BIN
build/install/snap/src/mysql/support-files/.mysql.server.swp
Normal file
Binary file not shown.
315
build/install/snap/src/mysql/support-files/mysql.server
Executable file
315
build/install/snap/src/mysql/support-files/mysql.server
Executable file
@ -0,0 +1,315 @@
|
||||
#!/bin/sh
|
||||
# Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
|
||||
# This file is public domain and comes with NO WARRANTY of any kind
|
||||
|
||||
# MySQL daemon start/stop script.
|
||||
|
||||
# Usually this is put in /etc/init.d (at least on machines SYSV R4 based
|
||||
# systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql.
|
||||
# When this is done the mysql server will be started when the machine is
|
||||
# started and shut down when the systems goes down.
|
||||
|
||||
# Comments to support chkconfig on RedHat Linux
|
||||
# chkconfig: 2345 64 36
|
||||
# description: A very fast and reliable SQL database engine.
|
||||
|
||||
# Comments to support LSB init script conventions
|
||||
### BEGIN INIT INFO
|
||||
# Provides: mysql
|
||||
# Required-Start: $local_fs $network $remote_fs
|
||||
# Should-Start: ypbind nscd ldap ntpd xntpd
|
||||
# Required-Stop: $local_fs $network $remote_fs
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: start and stop MySQL
|
||||
# Description: MySQL is a very fast and reliable SQL database engine.
|
||||
### END INIT INFO
|
||||
|
||||
# If you install MySQL on some other places than /, then you
|
||||
# have to do one of the following things for this script to work:
|
||||
#
|
||||
# - Run this script from within the MySQL installation directory
|
||||
# - Create a /etc/my.cnf file with the following information:
|
||||
# [mysqld]
|
||||
# basedir=<path-to-mysql-installation-directory>
|
||||
# - Add the above to any other configuration file (for example ~/.my.ini)
|
||||
# and copy my_print_defaults to /usr/bin
|
||||
# - Add the path to the mysql-installation-directory to the basedir variable
|
||||
# below.
|
||||
#
|
||||
# If you want to affect other MySQL variables, you should make your changes
|
||||
# in the /etc/my.cnf, ~/.my.cnf or other MySQL configuration files.
|
||||
|
||||
# If you change base dir, you must also change datadir. These may get
|
||||
# overwritten by settings in the MySQL configuration files.
|
||||
|
||||
# shellcheck source=src/mysql/utilities/mysql-utilities
|
||||
. "$SNAP/utilities/mysql-utilities"
|
||||
|
||||
basedir="$SNAP"
|
||||
datadir="$SNAP_DATA/mysql"
|
||||
|
||||
# Default value, in seconds, afterwhich the script should timeout waiting
|
||||
# for server start.
|
||||
# Value here is overriden by value in my.cnf.
|
||||
# 0 means don't wait at all
|
||||
# Negative numbers mean to wait indefinitely
|
||||
service_startup_timeout=900
|
||||
|
||||
# Lock directory for RedHat / SuSE.
|
||||
lockdir="$SNAP_DATA/mysql/lock"
|
||||
lock_file_path="$lockdir/mysql"
|
||||
|
||||
# The following variables are only set for letting mysql.server find things.
|
||||
|
||||
# Set some defaults
|
||||
mysqld_pid_file_path="$MYSQL_PIDFILE"
|
||||
if test -z "$basedir"
|
||||
then
|
||||
basedir=/
|
||||
bindir=//bin
|
||||
if test -z "$datadir"
|
||||
then
|
||||
datadir=//data
|
||||
fi
|
||||
libexecdir=//bin
|
||||
else
|
||||
bindir="$basedir/bin"
|
||||
if test -z "$datadir"
|
||||
then
|
||||
datadir="$basedir/data"
|
||||
fi
|
||||
libexecdir="$basedir/libexec"
|
||||
fi
|
||||
|
||||
#
|
||||
# Use LSB init script functions for printing messages, if possible
|
||||
#
|
||||
lsb_functions="/lib/lsb/init-functions"
|
||||
if test -f $lsb_functions ; then
|
||||
. $lsb_functions
|
||||
else
|
||||
log_success_msg()
|
||||
{
|
||||
echo " SUCCESS! $*"
|
||||
}
|
||||
log_failure_msg()
|
||||
{
|
||||
echo " ERROR! $*"
|
||||
}
|
||||
fi
|
||||
|
||||
PATH="/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin"
|
||||
export PATH
|
||||
|
||||
mode=$1 # start or stop
|
||||
|
||||
[ $# -ge 1 ] && shift
|
||||
|
||||
|
||||
other_args="$*" # uncommon, but needed when called from an RPM upgrade action
|
||||
# Expected: "--skip-networking --skip-grant-tables"
|
||||
# They are not checked here, intentionally, as it is the resposibility
|
||||
# of the "spec" file author to give correct arguments only.
|
||||
|
||||
# Upstream mysql stuff, no need to fix this
|
||||
# shellcheck disable=SC2116,SC2039
|
||||
case "$(echo "testing\c")","$(echo -n testing)" in
|
||||
*c*,-n*) echo_n="" echo_c="" ;;
|
||||
*c*,*) echo_n=-n echo_c="" ;;
|
||||
*) echo_n="" echo_c='\c' ;;
|
||||
esac
|
||||
|
||||
wait_for_pid () {
|
||||
verb="$1" # created | removed
|
||||
pid="$2" # process ID of the program operating on the pid-file
|
||||
pid_file_path="$3" # path to the PID file.
|
||||
|
||||
i=0
|
||||
avoid_race_condition="by checking again"
|
||||
|
||||
while test "$i" -ne "$service_startup_timeout" ; do
|
||||
|
||||
case "$verb" in
|
||||
'created')
|
||||
# wait for a PID-file to pop into existence.
|
||||
test -s "$pid_file_path" && i='' && break
|
||||
;;
|
||||
'removed')
|
||||
# wait for this PID-file to disappear
|
||||
test ! -s "$pid_file_path" && i='' && break
|
||||
;;
|
||||
*)
|
||||
echo "wait_for_pid () usage: wait_for_pid created|removed pid pid_file_path"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# if server isn't running, then pid-file will never be updated
|
||||
if test -n "$pid"; then
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
: # the server still runs
|
||||
else
|
||||
# The server may have exited between the last pid-file check and now.
|
||||
if test -n "$avoid_race_condition"; then
|
||||
avoid_race_condition=""
|
||||
continue # Check again.
|
||||
fi
|
||||
|
||||
# there's nothing that will affect the file.
|
||||
log_failure_msg "The server quit without updating PID file ($pid_file_path)."
|
||||
return 1 # not waiting any more.
|
||||
fi
|
||||
fi
|
||||
|
||||
echo $echo_n ".$echo_c"
|
||||
i=$((i + 1))
|
||||
sleep 1
|
||||
|
||||
done
|
||||
|
||||
if test -z "$i" ; then
|
||||
log_success_msg
|
||||
return 0
|
||||
else
|
||||
log_failure_msg
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Set pid file if not given
|
||||
#
|
||||
if test -z "$mysqld_pid_file_path"
|
||||
then
|
||||
mysqld_pid_file_path="$datadir"/"$(hostname)".pid
|
||||
else
|
||||
case "$mysqld_pid_file_path" in
|
||||
/* ) ;;
|
||||
* ) mysqld_pid_file_path="$datadir/$mysqld_pid_file_path" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
case "$mode" in
|
||||
'start')
|
||||
# Start daemon
|
||||
|
||||
# Safeguard (relative paths, core dumps..)
|
||||
cd "$basedir" || exit
|
||||
|
||||
echo $echo_n "Starting MySQL"
|
||||
if test -x "$bindir/mysqld_safe"
|
||||
then
|
||||
# Give extra arguments to mysqld with the my.cnf file. This script
|
||||
# may be overwritten at next upgrade.
|
||||
"$bindir/mysqld_safe" --datadir="$datadir" --pid-file="$mysqld_pid_file_path" --lc-messages-dir="$SNAP/share" --socket="$MYSQL_SOCKET" "$other_args" >/dev/null 2>&1 &
|
||||
wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$?
|
||||
|
||||
# Make lock for RedHat / SuSE
|
||||
if test -w "$lockdir"
|
||||
then
|
||||
touch "$lock_file_path"
|
||||
fi
|
||||
|
||||
exit $return_value
|
||||
else
|
||||
log_failure_msg "Couldn't find MySQL server ($bindir/mysqld_safe)"
|
||||
fi
|
||||
;;
|
||||
|
||||
'stop')
|
||||
# Stop daemon. We use a signal here to avoid having to know the
|
||||
# root password.
|
||||
|
||||
if test -s "$mysqld_pid_file_path"
|
||||
then
|
||||
# signal mysqld_safe that it needs to stop
|
||||
touch "$mysqld_pid_file_path.shutdown"
|
||||
|
||||
mysqld_pid="$(cat "$mysqld_pid_file_path")"
|
||||
|
||||
if (kill -0 "$mysqld_pid" 2>/dev/null)
|
||||
then
|
||||
echo $echo_n "Shutting down MySQL"
|
||||
kill "$mysqld_pid"
|
||||
# mysqld should remove the pid file when it exits, so wait for it.
|
||||
wait_for_pid removed "$mysqld_pid" "$mysqld_pid_file_path"; return_value=$?
|
||||
else
|
||||
log_failure_msg "MySQL server process #$mysqld_pid is not running!"
|
||||
rm "$mysqld_pid_file_path"
|
||||
fi
|
||||
|
||||
# Delete lock for RedHat / SuSE
|
||||
if test -f "$lock_file_path"
|
||||
then
|
||||
rm -f "$lock_file_path"
|
||||
fi
|
||||
exit $return_value
|
||||
else
|
||||
log_failure_msg "MySQL server PID file could not be found!"
|
||||
fi
|
||||
;;
|
||||
|
||||
'restart')
|
||||
# Stop the service and regardless of whether it was
|
||||
# running or not, start it again.
|
||||
if $0 stop "$other_args"; then
|
||||
$0 start "$other_args"
|
||||
else
|
||||
log_failure_msg "Failed to stop running server, so refusing to try to start."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
'reload'|'force-reload')
|
||||
if test -s "$mysqld_pid_file_path" ; then
|
||||
read -r mysqld_pid < "$mysqld_pid_file_path"
|
||||
kill -HUP "$mysqld_pid" && log_success_msg "Reloading service MySQL"
|
||||
touch "$mysqld_pid_file_path"
|
||||
else
|
||||
log_failure_msg "MySQL PID file could not be found!"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
'status')
|
||||
# First, check to see if pid file exists
|
||||
if test -s "$mysqld_pid_file_path" ; then
|
||||
read -r mysqld_pid < "$mysqld_pid_file_path"
|
||||
if kill -0 "$mysqld_pid" 2>/dev/null ; then
|
||||
log_success_msg "MySQL running ($mysqld_pid)"
|
||||
exit 0
|
||||
else
|
||||
log_failure_msg "MySQL is not running, but PID file exists"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Try to find appropriate mysqld process
|
||||
mysqld_pid="$(pidof "$libexecdir/mysqld")"
|
||||
|
||||
# test if multiple pids exist
|
||||
pid_count="$(echo "$mysqld_pid" | wc -w)"
|
||||
if test "$pid_count" -gt 1 ; then
|
||||
log_failure_msg "Multiple MySQL running but PID file could not be found ($mysqld_pid)"
|
||||
exit 5
|
||||
elif test -z "$mysqld_pid" ; then
|
||||
if test -f "$lock_file_path" ; then
|
||||
log_failure_msg "MySQL is not running, but lock file ($lock_file_path) exists"
|
||||
exit 2
|
||||
fi
|
||||
log_failure_msg "MySQL is not running"
|
||||
exit 3
|
||||
else
|
||||
log_failure_msg "MySQL is running but PID file could not be found"
|
||||
exit 4
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# usage
|
||||
basename="$(basename "$0")"
|
||||
echo "Usage: $basename {start|stop|restart|reload|force-reload|status} [ MySQL server options ]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
72
build/install/snap/src/mysql/utilities/mysql-utilities
Executable file
72
build/install/snap/src/mysql/utilities/mysql-utilities
Executable file
@ -0,0 +1,72 @@
|
||||
#!/bin/sh
|
||||
|
||||
export MYSQL_PIDFILE="/tmp/pids/mysql.pid"
|
||||
export MYSQL_SOCKET="/tmp/sockets/mysql.sock"
|
||||
export ONLYOFFICE_PASSWORD_FILE="$SNAP_DATA/mysql/onlyoffice_password"
|
||||
MYSQL_SETUP_LOCKFILE="/tmp/locks/mysql-setup"
|
||||
|
||||
mkdir -p "$(dirname "$MYSQL_PIDFILE")"
|
||||
mkdir -p "$(dirname "$MYSQL_SOCKET")"
|
||||
chmod 750 "$(dirname "$MYSQL_PIDFILE")"
|
||||
chmod 750 "$(dirname "$MYSQL_SOCKET")"
|
||||
|
||||
mysql_is_running()
|
||||
{
|
||||
# Arguments:
|
||||
# -f: Force the check, i.e. ignore if it's currently in setup
|
||||
[ -f "$MYSQL_PIDFILE" ] && [ -S "$MYSQL_SOCKET" ] && (! mysql_setup_running || [ "$1" = "-f" ])
|
||||
}
|
||||
|
||||
wait_for_mysql()
|
||||
{
|
||||
# Arguments:
|
||||
# -f: Force the check, i.e. ignore if it's currently in setup
|
||||
if ! mysql_is_running "$@"; then
|
||||
printf "Waiting for MySQL... "
|
||||
while ! mysql_is_running "$@"; do
|
||||
sleep 1
|
||||
done
|
||||
printf "done\n"
|
||||
fi
|
||||
}
|
||||
|
||||
mysql_setup_running()
|
||||
{
|
||||
[ -f "$MYSQL_SETUP_LOCKFILE" ]
|
||||
}
|
||||
|
||||
set_mysql_setup_running()
|
||||
{
|
||||
touch "$MYSQL_SETUP_LOCKFILE"
|
||||
}
|
||||
|
||||
set_mysql_setup_not_running()
|
||||
{
|
||||
rm -f "$MYSQL_SETUP_LOCKFILE"
|
||||
}
|
||||
|
||||
mysql_pid()
|
||||
{
|
||||
if mysql_is_running; then
|
||||
cat "$MYSQL_PIDFILE"
|
||||
else
|
||||
echo "Unable to get MySQL PID as it's not yet running" >&2
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
mysql_set_onlyoffice_password()
|
||||
{
|
||||
echo "$1" > "$ONLYOFFICE_PASSWORD_FILE"
|
||||
chmod 600 "$ONLYOFFICE_PASSWORD_FILE"
|
||||
}
|
||||
|
||||
mysql_get_onlyoffice_password()
|
||||
{
|
||||
if [ -f "$ONLYOFFICE_PASSWORD_FILE" ]; then
|
||||
cat "$ONLYOFFICE_PASSWORD_FILE"
|
||||
else
|
||||
echo "MySQL ONLYOFFICE password has not yet been generated" >&2
|
||||
echo ""
|
||||
fi
|
||||
}
|
12
build/install/snap/src/nginx/bin/start_nginx
Executable file
12
build/install/snap/src/nginx/bin/start_nginx
Executable file
@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
# shellcheck source=src/nginx/utilities/nginx-utilities
|
||||
. "$SNAP/utilities/nginx-utilities"
|
||||
|
||||
cp -dfr ${SNAP}/config/nginx-config/* ${SNAP_DATA}/nginx/config
|
||||
|
||||
sed -e "s|\${SNAP}|$SNAP|;s|\${SNAP_DATA}|$SNAP_DATA|;s|\${NGINX_PIDFILE}|$NGINX_PIDFILE|;s|\${ONLYOFFICE_SOCKET}|$ONLYOFFICE_SOCKET|;s|\${ONLYOFFICE_API_SYSTEM_SOCKET}|$ONLYOFFICE_API_SYSTEM_SOCKET|" -i ${SNAP_DATA}/nginx/config/conf.d/onlyoffice
|
||||
sed -e "s|\${SNAP}|$SNAP|;s|\${SNAP_DATA}|$SNAP_DATA|;s|\${NGINX_PIDFILE}|$NGINX_PIDFILE|;s|\${ONLYOFFICE_SOCKET}|$ONLYOFFICE_SOCKET|;s|\${ONLYOFFICE_API_SYSTEM_SOCKET}|$ONLYOFFICE_API_SYSTEM_SOCKET|" -i ${SNAP_DATA}/nginx/config/conf.d/includes/onlyoffice-communityserver-common.conf
|
||||
sed -e "s|\${SNAP}|$SNAP|;s|\${SNAP_DATA}|$SNAP_DATA|;s|\${NGINX_PIDFILE}|$NGINX_PIDFILE|;s|\${ONLYOFFICE_SOCKET}|$ONLYOFFICE_SOCKET|;s|\${ONLYOFFICE_API_SYSTEM_SOCKET}|$ONLYOFFICE_API_SYSTEM_SOCKET|" -i ${SNAP_DATA}/nginx/config/nginx.conf
|
||||
|
||||
exec "$SNAP/sbin/nginx" "-c" "$SNAP_DATA/nginx/config/nginx.conf" "-p" "$SNAP_DATA/nginx" "-g" "daemon off;" "$@"
|
@ -0,0 +1,43 @@
|
||||
upstream fastcgi_backend {
|
||||
server unix:/var/run/onlyoffice/onlyoffice.socket;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
fastcgi_keep_conn on;
|
||||
fastcgi_index Default.aspx;
|
||||
fastcgi_intercept_errors on;
|
||||
|
||||
|
||||
include fastcgi_params;
|
||||
|
||||
fastcgi_param HTTP_X_REWRITER_URL $http_x_rewriter_url;
|
||||
fastcgi_param SERVER_NAME $host;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO "";
|
||||
|
||||
fastcgi_read_timeout 600;
|
||||
fastcgi_send_timeout 600;
|
||||
|
||||
|
||||
location / {
|
||||
root /var/www/onlyoffice/WebStudio/;
|
||||
expires 0;
|
||||
add_header Cache-Control no-cache;
|
||||
rewrite ^(.*)$ /StartConfigure.htm break;
|
||||
}
|
||||
|
||||
location /api {
|
||||
fastcgi_pass fastcgi_backend;
|
||||
break;
|
||||
}
|
||||
|
||||
location ~* ^/(warmup[2-9]?)/ {
|
||||
rewrite /warmup([^/]*)/(.*) /$2 break;
|
||||
fastcgi_pass unix:/var/run/onlyoffice/onlyoffice$1.socket;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,129 @@
|
||||
upstream fastcgi_backend_apisystem {
|
||||
server unix:/var/run/onlyoffice/onlyofficeApiSystem.socket;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
upstream fastcgi_backend {
|
||||
server unix:/var/run/onlyoffice/onlyoffice.socket;
|
||||
keepalive {{ONLYOFFICE_NIGNX_KEEPLIVE}};
|
||||
}
|
||||
|
||||
fastcgi_cache_path /var/cache/nginx/onlyoffice
|
||||
levels=1:2
|
||||
keys_zone=onlyoffice:16m
|
||||
max_size=256m
|
||||
inactive=1d;
|
||||
|
||||
geo $ip_external {
|
||||
default 1;
|
||||
{{DOCKER_ONLYOFFICE_SUBNET}} 0;
|
||||
127.0.0.1 0;
|
||||
}
|
||||
|
||||
map $http_host $this_host {
|
||||
"" $host;
|
||||
default $http_host;
|
||||
}
|
||||
|
||||
map $http_x_forwarded_proto $the_scheme {
|
||||
default $http_x_forwarded_proto;
|
||||
"" $scheme;
|
||||
}
|
||||
|
||||
map $http_x_forwarded_host $the_host {
|
||||
default $http_x_forwarded_host;
|
||||
"" $this_host;
|
||||
}
|
||||
|
||||
## Normal HTTP host
|
||||
server {
|
||||
listen 0.0.0.0:80;
|
||||
listen [::]:80 default_server;
|
||||
server_name _;
|
||||
server_tokens off;
|
||||
|
||||
root /nowhere; ## root doesn't have to be a valid path since we are redirecting
|
||||
|
||||
location / {
|
||||
if ($ip_external) {
|
||||
## Redirects all traffic to the HTTPS host
|
||||
rewrite ^ https://$host$request_uri? permanent;
|
||||
}
|
||||
|
||||
|
||||
client_max_body_size 100m;
|
||||
|
||||
proxy_pass https://127.0.0.1;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_ssl_verify off;
|
||||
}
|
||||
}
|
||||
|
||||
## HTTPS host
|
||||
server {
|
||||
listen 0.0.0.0:443 ssl;
|
||||
listen [::]:443 ssl default_server;
|
||||
server_tokens off;
|
||||
root /usr/share/nginx/html;
|
||||
|
||||
## Increase this if you want to upload large attachments
|
||||
client_max_body_size 100m;
|
||||
|
||||
## Strong SSL Security
|
||||
## https://cipherli.st/
|
||||
ssl on;
|
||||
ssl_certificate {{SSL_CERTIFICATE_PATH}};
|
||||
ssl_certificate_key {{SSL_KEY_PATH}};
|
||||
ssl_verify_client {{SSL_VERIFY_CLIENT}};
|
||||
ssl_client_certificate {{CA_CERTIFICATES_PATH}};
|
||||
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
|
||||
ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_tickets off; # Requires nginx >= 1.5.9
|
||||
|
||||
add_header Strict-Transport-Security "max-age={{ONLYOFFICE_HTTPS_HSTS_MAXAGE}}; includeSubDomains; preload" always;
|
||||
# add_header X-Frame-Options DENY;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
|
||||
## [Optional] If your certficate has OCSP, enable OCSP stapling to reduce the overhead and latency of running SSL.
|
||||
## Replace with your ssl_trusted_certificate. For more info see:
|
||||
## - https://medium.com/devops-programming/4445f4862461
|
||||
## - https://www.ruby-forum.com/topic/4419319
|
||||
## - https://www.digitalocean.com/community/tutorials/how-to-configure-ocsp-stapling-on-apache-and-nginx
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
ssl_trusted_certificate {{SSL_OCSP_CERTIFICATE_PATH}};
|
||||
resolver 8.8.8.8 8.8.4.4 127.0.0.11 valid=300s; # Can change to your DNS resolver if desired
|
||||
resolver_timeout 10s;
|
||||
|
||||
## [Optional] Generate a stronger DHE parameter:
|
||||
## cd /etc/ssl/certs
|
||||
## sudo openssl dhparam -out dhparam.pem 4096
|
||||
##
|
||||
ssl_dhparam {{SSL_DHPARAM_PATH}};
|
||||
|
||||
large_client_header_buffers 4 16k;
|
||||
|
||||
set $X_REWRITER_URL $the_scheme://$the_host;
|
||||
|
||||
if ($http_x_rewriter_url != '') {
|
||||
set $X_REWRITER_URL $http_x_rewriter_url ;
|
||||
}
|
||||
|
||||
|
||||
include /etc/nginx/includes/onlyoffice-communityserver-*.conf;
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,83 @@
|
||||
location / {
|
||||
root ${SNAP}/var/www/onlyoffice/WebStudio/;
|
||||
index index.html index.htm default.aspx Default.aspx;
|
||||
|
||||
client_max_body_size 4G;
|
||||
|
||||
fastcgi_pass fastcgi_backend;
|
||||
fastcgi_keep_conn on;
|
||||
|
||||
error_page 404 /404.htm;
|
||||
|
||||
gzip off;
|
||||
gzip_comp_level 2;
|
||||
gzip_min_length 1000;
|
||||
gzip_proxied expired no-cache no-store private auth;
|
||||
gzip_types text/html application/x-javascript text/css application/xml;
|
||||
|
||||
fastcgi_index Default.aspx;
|
||||
fastcgi_intercept_errors on;
|
||||
|
||||
include ${SNAP}/conf/fastcgi_params;
|
||||
|
||||
fastcgi_param HTTP_X_REWRITER_URL $X_REWRITER_URL;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO "";
|
||||
|
||||
fastcgi_read_timeout 600;
|
||||
fastcgi_send_timeout 600;
|
||||
|
||||
location ~* (^\/(?:skins|products|addons).*\.(?:jpg|jpeg|gif|png|svg|ico)$)|(.*bundle/(?!clientscript).*) {
|
||||
fastcgi_pass fastcgi_backend;
|
||||
|
||||
fastcgi_temp_path ${SNAP_DATA}/nginx/cache/tmp 1 2;
|
||||
fastcgi_cache onlyoffice;
|
||||
fastcgi_cache_key "$scheme|$request_method|$host|$request_uri|$query_string";
|
||||
fastcgi_cache_use_stale updating error timeout invalid_header http_500;
|
||||
fastcgi_cache_valid 1d;
|
||||
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
|
||||
|
||||
add_header X-Fastcgi-Cache $upstream_cache_status;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
expires max;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
location /apisystem {
|
||||
rewrite /apisystem(.*) /$1 break;
|
||||
|
||||
root ${SNAP}/var/www/onlyoffice/ApiSystem/;
|
||||
index index.html index.htm default.aspx Default.aspx;
|
||||
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
add_header X-Frame-Options DENY;
|
||||
|
||||
client_max_body_size 4G;
|
||||
|
||||
fastcgi_keep_conn on;
|
||||
fastcgi_pass fastcgi_backend_apisystem;
|
||||
|
||||
include ${SNAP}/conf/fastcgi_params;
|
||||
|
||||
set $X_REWRITER_URL $scheme://$http_host;
|
||||
|
||||
if ($http_x_rewriter_url != '') {
|
||||
set $X_REWRITER_URL $http_x_rewriter_url ;
|
||||
}
|
||||
|
||||
|
||||
fastcgi_param HTTP_X_REWRITER_URL $X_REWRITER_URL;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO "";
|
||||
|
||||
fastcgi_read_timeout 600;
|
||||
fastcgi_send_timeout 600;
|
||||
}
|
||||
|
||||
location /filesData {
|
||||
rewrite /filesData/var/www/onlyoffice/Data/Products/Files(.*) /$1 break;
|
||||
root ${SNAP_DATA}/onlyoffice/Data/Products/Files;
|
||||
internal;
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
upstream fastcgi_backend_apisystem {
|
||||
server unix:/var/run/onlyoffice/onlyofficeApiSystem.socket;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
upstream fastcgi_backend {
|
||||
server unix:/var/run/onlyoffice/onlyoffice.socket;
|
||||
keepalive {{ONLYOFFICE_NIGNX_KEEPLIVE}};
|
||||
}
|
||||
|
||||
fastcgi_cache_path /var/cache/nginx/onlyoffice
|
||||
levels=1:2
|
||||
keys_zone=onlyoffice:16m
|
||||
max_size=256m
|
||||
inactive=1d;
|
||||
|
||||
map $http_host $this_host {
|
||||
"" $host;
|
||||
default $http_host;
|
||||
}
|
||||
|
||||
map $http_x_forwarded_proto $the_scheme {
|
||||
default $http_x_forwarded_proto;
|
||||
"" $scheme;
|
||||
}
|
||||
|
||||
map $http_x_forwarded_host $the_host {
|
||||
default $http_x_forwarded_host;
|
||||
"" $this_host;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
|
||||
large_client_header_buffers 4 16k;
|
||||
|
||||
set $X_REWRITER_URL $the_scheme://$the_host;
|
||||
|
||||
if ($http_x_rewriter_url != '') {
|
||||
set $X_REWRITER_URL $http_x_rewriter_url ;
|
||||
}
|
||||
|
||||
include /etc/nginx/includes/onlyoffice-communityserver-*.conf;
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
location /.well-known/acme-challenge {
|
||||
root /var/www/onlyoffice/Data/certs/;
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;
|
||||
include /etc/nginx/sites-enabled/*;
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
location /controlpanel {
|
||||
proxy_pass http://{{CONTROL_PANEL_HOST_ADDR}};
|
||||
|
||||
client_max_body_size 100m;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
|
||||
}
|
||||
|
||||
location /sso/ {
|
||||
proxy_pass http://{{SERVICE_SSO_AUTH_HOST_ADDR}}:9834;
|
||||
|
||||
client_max_body_size 100m;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
|
||||
|
||||
proxy_redirect / /;
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
location ~* ^/ds-vpath/ {
|
||||
rewrite /ds-vpath/(.*) /$1 break;
|
||||
proxy_pass {{DOCUMENT_SERVER_HOST_ADDR}};
|
||||
proxy_redirect off;
|
||||
|
||||
client_max_body_size 100m;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $the_host/ds-vpath;
|
||||
proxy_set_header X-Forwarded-Proto $the_scheme;
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
location /addons/talk/http-poll/httppoll.ashx {
|
||||
proxy_pass http://localhost:5280/http-poll/;
|
||||
proxy_buffering off;
|
||||
client_max_body_size 10m;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
}
|
||||
|
||||
|
||||
location /socketio {
|
||||
rewrite /socketio/(.*) /$1 break;
|
||||
proxy_pass http://localhost:9899;
|
||||
|
||||
client_max_body_size 100m;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
proxy_set_header X-Forwarded-Proto "http";
|
||||
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
|
||||
}
|
||||
|
||||
|
||||
location /healthcheck {
|
||||
rewrite /healthcheck(.*) /$1 break;
|
||||
proxy_pass http://localhost:9810;
|
||||
proxy_redirect ~*/(.*) /healthcheck/$1;
|
||||
|
||||
client_max_body_size 100m;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
upstream fastcgi_backend_apisystem {
|
||||
server unix:${ONLYOFFICE_API_SYSTEM_SOCKET};
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
upstream fastcgi_backend {
|
||||
server unix:${ONLYOFFICE_SOCKET};
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
fastcgi_cache_path ${SNAP_DATA}/nginx/cache/onlyoffice
|
||||
levels=1:2
|
||||
keys_zone=onlyoffice:16m
|
||||
max_size=256m
|
||||
inactive=1d;
|
||||
|
||||
map $http_host $this_host {
|
||||
"" $host;
|
||||
default $http_host;
|
||||
}
|
||||
|
||||
map $http_x_forwarded_proto $the_scheme {
|
||||
default $http_x_forwarded_proto;
|
||||
"" $scheme;
|
||||
}
|
||||
|
||||
map $http_x_forwarded_host $the_host {
|
||||
default $http_x_forwarded_host;
|
||||
"" $this_host;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
|
||||
large_client_header_buffers 4 16k;
|
||||
|
||||
set $X_REWRITER_URL $the_scheme://$the_host;
|
||||
|
||||
if ($http_x_rewriter_url != '') {
|
||||
set $X_REWRITER_URL $http_x_rewriter_url ;
|
||||
}
|
||||
|
||||
include ${SNAP_DATA}/nginx/config/conf.d/includes/onlyoffice-communityserver-*.conf;
|
||||
}
|
30
build/install/snap/src/nginx/config/nginx-config/nginx.conf
Normal file
30
build/install/snap/src/nginx/config/nginx-config/nginx.conf
Normal file
@ -0,0 +1,30 @@
|
||||
user root;
|
||||
worker_processes 2;
|
||||
|
||||
error_log ${SNAP_DATA}/nginx/logs/error.log warn;
|
||||
pid ${NGINX_PIDFILE};
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1048576;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include ${SNAP}/conf/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log ${SNAP_DATA}/nginx/logs/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;
|
||||
include ${SNAP_DATA}/nginx/config/conf.d/onlyoffice;
|
||||
}
|
17
build/install/snap/src/nginx/utilities/nginx-utilities
Executable file
17
build/install/snap/src/nginx/utilities/nginx-utilities
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
export NGINX_PIDFILE="/tmp/pids/nginx.pid"
|
||||
|
||||
mkdir -p "$(dirname "$NGINX_PIDFILE")"
|
||||
chmod 750 "$(dirname "$NGINX_PIDFILE")"
|
||||
|
||||
mkdir -p ${SNAP_DATA}/nginx/logs
|
||||
chmod 750 ${SNAP_DATA}/nginx/logs
|
||||
|
||||
mkdir -p ${SNAP_DATA}/nginx/cache
|
||||
chmod 750 ${SNAP_DATA}/nginx/cache
|
||||
|
||||
mkdir -p ${SNAP_DATA}/nginx/config
|
||||
chmod 750 ${SNAP_DATA}/nginx/config
|
||||
|
||||
|
87
build/install/snap/src/onlyoffice/bin/start_monoserve
Executable file
87
build/install/snap/src/onlyoffice/bin/start_monoserve
Executable file
@ -0,0 +1,87 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
|
||||
# shellcheck source=src/mysql/utilities/mysql-utilities
|
||||
. "$SNAP/utilities/mysql-utilities"
|
||||
|
||||
# shellcheck source=src/onlyoffice/utilities/monoserve-utilities
|
||||
. "${SNAP}/utilities/monoserve-utilities"
|
||||
|
||||
# shellcheck source=src/redis/utilities/redis-utilities
|
||||
. "$SNAP/utilities/redis-utilities"
|
||||
|
||||
|
||||
wait_for_redis
|
||||
wait_for_mysql
|
||||
|
||||
DB_NAME="onlyoffice";
|
||||
DB_HOST="localhost";
|
||||
DB_USER="onlyoffice";
|
||||
DB_PWD=$( mysql_get_onlyoffice_password );
|
||||
|
||||
|
||||
ONLYOFFICE_CORE_MACHINEKEY=$( onlyoffice_get_core_machine_key );
|
||||
|
||||
cp -drf ${SNAP}/config/hyperfastcgi-config/* ${SNAP_DATA}/hyperfastcgi/
|
||||
|
||||
[ -e ${ONLYOFFCE_SOCKET} ] && rm -f ${ONLYOFFCE_SOCKET}
|
||||
|
||||
sed -e "s|\${SNAP}|$SNAP|;s|\${SNAP_DATA}|$SNAP_DATA|;s|\${ONLYOFFICE_SOCKET}|$ONLYOFFICE_SOCKET|" -i ${SNAP_DATA}/hyperfastcgi/onlyoffice
|
||||
|
||||
mkdir -p ${SNAP_DATA}/onlyoffice/config/WebStudio/
|
||||
cp -dfr ${SNAP}/var/www/onlyoffice/WebStudio/*.config ${SNAP_DATA}/onlyoffice/config/WebStudio/
|
||||
|
||||
sed "/core.machinekey/s!value=\".*\"!value=\"${ONLYOFFICE_CORE_MACHINEKEY}\"!g" -i ${SNAP_DATA}/onlyoffice/config/WebStudio/web.appsettings.config
|
||||
sed "s!/var/log/onlyoffice/!${SNAP_DATA}/onlyoffice/logs/!g" -i ${SNAP_DATA}/onlyoffice/config/WebStudio/web.log4net.config
|
||||
sed "s|\.*\\\Data\\\|${SNAP_DATA}/onlyoffice/data/|g" -i ${SNAP_DATA}/onlyoffice/config/WebStudio/web.storage.config
|
||||
|
||||
sed "s|Password=.*;|Password=${DB_PWD};|g" -i ${SNAP_DATA}/onlyoffice/config/WebStudio/web.connections.config
|
||||
sed "s|User\\s*ID=.*;|User\\s*ID=${DB_USER};|g" -i ${SNAP_DATA}/onlyoffice/config/WebStudio/web.connections.config
|
||||
|
||||
|
||||
export ONLYOFFICE_APP_CONFIG_FILE="${SNAP_DATA}/onlyoffice/config/WebStudio/Web.config";
|
||||
|
||||
MYSQL="mysql -h$DB_HOST -u$DB_USER -p$DB_PWD -S$MYSQL_SOCKET";
|
||||
|
||||
DB_TABLES_COUNT=$($MYSQL --silent --skip-column-names -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='${DB_NAME}'");
|
||||
|
||||
if [ "${DB_TABLES_COUNT}" -eq "0" ]; then
|
||||
|
||||
$MYSQL "$DB_NAME" < $SNAP/var/www/onlyoffice/Sql/onlyoffice.sql
|
||||
$MYSQL "$DB_NAME" < $SNAP/var/www/onlyoffice/Sql/onlyoffice.data.sql
|
||||
$MYSQL "$DB_NAME" < $SNAP/var/www/onlyoffice/Sql/onlyoffice.resources.sql
|
||||
fi
|
||||
|
||||
for i in $(ls $SNAP/var/www/onlyoffice/Sql/onlyoffice.upgrade*); do
|
||||
$MYSQL "$DB_NAME" < ${i};
|
||||
done
|
||||
|
||||
# export mono variables
|
||||
export MONO_IOMAP=all
|
||||
export MONO_ASPNET_WEBCONFIG_CACHESIZE=2000
|
||||
export MONO_THREADS_PER_CPU=2000
|
||||
export MONO_OPTIONS="--server"
|
||||
export MONO_GC_PARAMS=nursery-size=64m
|
||||
|
||||
PKG_DIR=$SNAP/usr
|
||||
|
||||
export MONO_PATH=$PKG_DIR/lib/mono/4.5
|
||||
export MONO_CONFIG=$SNAP/etc/mono/config
|
||||
export MONO_CFG_DIR=$SNAP/etc
|
||||
export C_INCLUDE_PATH=${PKG_DIR}/include
|
||||
export MONO_REGISTRY_PATH=~/.mono/registry
|
||||
export MONO_GAC_PREFIX=$PKG_DIR/lib/mono/gac/
|
||||
#export LD_LIBRARY_PATH=$PKG_DIR/lib:$LD_LIBRARY_PATH
|
||||
|
||||
export LD_RUN_PATH=$LD_LIBRARY_PATH
|
||||
#export LD_DEBUG=files
|
||||
|
||||
export PKG_CONFIG_PATH=$PKG_DIR/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
export ACLOCAL_PATH=${PKG_DIR}/share/aclocal
|
||||
#export MONO_LOG_LEVEL=debug
|
||||
#export FONTCONFIG_PATH=${PKG_DIR}/etc/fonts
|
||||
#export XDG_DATA_HOME=${PKG_DIR}/etc/fonts
|
||||
|
||||
|
||||
exec ${SNAP}/usr/bin/mono ${SNAP}/usr/lib/hyperfastcgi/4.0/HyperFastCgi.exe /config=${SNAP_DATA}/hyperfastcgi/onlyoffice /logfile=${SNAP_DATA}/onlyoffice/logs/onlyoffice.log
|
@ -0,0 +1,24 @@
|
||||
<configuration>
|
||||
<server type="HyperFastCgi.ApplicationServers.SimpleApplicationServer">
|
||||
<root-dir>${SNAP}/var/www/onlyoffice/WebStudio</root-dir>
|
||||
<threads min-worker="40" max-worker="0" min-io="4" max-io="0" />
|
||||
</server>
|
||||
<listener type="HyperFastCgi.Listeners.NativeListener">
|
||||
<apphost-transport type="HyperFastCgi.Transports.NativeTransport">
|
||||
<multithreading>Task</multithreading>
|
||||
</apphost-transport>
|
||||
<protocol>Unix</protocol>
|
||||
<address>//666@${ONLYOFFICE_SOCKET}</address>
|
||||
</listener>
|
||||
<apphost type="HyperFastCgi.AppHosts.AspNet.AspNetApplicationHost">
|
||||
<log level="Error" write-to-console="false" />
|
||||
<add-trailing-slash>false</add-trailing-slash>
|
||||
</apphost>
|
||||
<web-applications>
|
||||
<web-application>
|
||||
<name>onlyoffice</name>
|
||||
<vpath>/</vpath>
|
||||
<path>.</path>
|
||||
</web-application>
|
||||
</web-applications>
|
||||
</configuration>
|
@ -0,0 +1,24 @@
|
||||
<configuration>
|
||||
<server type="HyperFastCgi.ApplicationServers.SimpleApplicationServer">
|
||||
<root-dir>${SNAP}/var/www/onlyoffice/ApiSystem</root-dir>
|
||||
<threads min-worker="40" max-worker="0" min-io="4" max-io="0" />
|
||||
</server>
|
||||
<listener type="HyperFastCgi.Listeners.NativeListener">
|
||||
<apphost-transport type="HyperFastCgi.Transports.NativeTransport">
|
||||
<multithreading>Task</multithreading>
|
||||
</apphost-transport>
|
||||
<protocol>Unix</protocol>
|
||||
<address>//666@${ONLYOFFICE_API_SYSTEM_SOCKET}</address>
|
||||
</listener>
|
||||
<apphost type="HyperFastCgi.AppHosts.AspNet.AspNetApplicationHost">
|
||||
<log level="Error" write-to-console="false" />
|
||||
<add-trailing-slash>false</add-trailing-slash>
|
||||
</apphost>
|
||||
<web-applications>
|
||||
<web-application>
|
||||
<name>onlyofficeApiSystem</name>
|
||||
<vpath>/</vpath>
|
||||
<path>.</path>
|
||||
</web-application>
|
||||
</web-applications>
|
||||
</configuration>
|
36
build/install/snap/src/onlyoffice/utilities/monoserve-utilities
Executable file
36
build/install/snap/src/onlyoffice/utilities/monoserve-utilities
Executable file
@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
export ONLYOFFICE_SOCKET="/tmp/sockets/onlyoffice.socket"
|
||||
export ONLYOFFICE_API_SYSTEM_SOCKET="/tmp/sockets/onlyofficeApiSystem.socket"
|
||||
export ONLYOFFICE_CORE_MACHINEKEY_FILE="$SNAP_DATA/onlyoffice/.onlyoffice_core_machine_key"
|
||||
|
||||
mkdir -p "$(dirname "$ONLYOFFICE_SOCKET")"
|
||||
chmod 750 "$(dirname "$ONLYOFFICE_SOCKET")"
|
||||
|
||||
mkdir -p "$(dirname "$ONLYOFFICE_API_SYSTEM_SOCKET")"
|
||||
chmod 750 "$(dirname "$ONLYOFFICE_API_SYSTEM_SOCKET")"
|
||||
|
||||
mkdir -p "$(dirname "$ONLYOFFICE_CORE_MACHINEKEY_FILE")"
|
||||
chmod 750 "$(dirname "$ONLYOFFICE_CORE_MACHINEKEY_FILE")"
|
||||
|
||||
mkdir -p $SNAP_DATA/hyperfastcgi
|
||||
chmod 750 $SNAP_DATA/hyperfastcgi
|
||||
|
||||
mkdir -p $SNAP_DATA/onlyoffice/logs
|
||||
chmod 750 $SNAP_DATA/onlyoffice/logs
|
||||
|
||||
mkdir -p $SNAP_DATA/onlyoffice/data
|
||||
chmod 750 $SNAP_DATA/onlyoffice/data
|
||||
|
||||
mkdir -p $SNAP_DATA/onlyoffice/config
|
||||
chmod 750 $SNAP_DATA/onlyoffice/config
|
||||
|
||||
onlyoffice_get_core_machine_key() {
|
||||
if [ ! -f "$ONLYOFFICE_CORE_MACHINEKEY_FILE" ]; then
|
||||
echo "$(tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c64)" > ${ONLYOFFICE_CORE_MACHINEKEY_FILE};
|
||||
chmod 600 ${ONLYOFFICE_CORE_MACHINEKEY_FILE};
|
||||
fi
|
||||
|
||||
cat "$ONLYOFFICE_CORE_MACHINEKEY_FILE";
|
||||
}
|
||||
|
@ -0,0 +1,92 @@
|
||||
From bb6c86ca997b2ca1b052cb83e91152220fe149ad Mon Sep 17 00:00:00 2001
|
||||
From: Kyle Fazzari <oracle@status.e4ward.com>
|
||||
Date: Fri, 25 Mar 2016 15:03:38 +0000
|
||||
Subject: [PATCH] Support compile-time disabling of setpriority().
|
||||
|
||||
This is to support running on systems such as Snappy Ubuntu Core,
|
||||
e.g. heavily confined using seccomp filters. In such a situation,
|
||||
without this commit, MySQL is aborted as soon as it tries to call
|
||||
setpriority(). With this commit, MySQL can be built without
|
||||
setpriority() by using -DWITH_INNODB_PAGE_CLEANER_PRIORITY=OFF,
|
||||
thus supporting such systems.
|
||||
|
||||
Signed-off-by: Kyle Fazzari <oracle@status.e4ward.com>
|
||||
---
|
||||
storage/innobase/buf/buf0flu.cc | 12 ++++++------
|
||||
storage/innobase/innodb.cmake | 5 +++++
|
||||
2 files changed, 11 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
|
||||
index 5a8a3567e0f..0961f757b1a 100644
|
||||
--- a/storage/innobase/buf/buf0flu.cc
|
||||
+++ b/storage/innobase/buf/buf0flu.cc
|
||||
@@ -2952,7 +2952,7 @@ pc_wait_finished(
|
||||
return(all_succeeded);
|
||||
}
|
||||
|
||||
-#ifdef UNIV_LINUX
|
||||
+#if defined(UNIV_LINUX) && defined(SET_PAGE_CLEANER_PRIORITY)
|
||||
/**
|
||||
Set priority for page_cleaner threads.
|
||||
@param[in] priority priority intended to set
|
||||
@@ -2967,7 +2967,7 @@ buf_flush_page_cleaner_set_priority(
|
||||
return(getpriority(PRIO_PROCESS, (pid_t)syscall(SYS_gettid))
|
||||
== priority);
|
||||
}
|
||||
-#endif /* UNIV_LINUX */
|
||||
+#endif /* UNIV_LINUX && SET_PAGE_CLEANER_PRIORITY */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/** Loop used to disable page cleaner threads. */
|
||||
@@ -3113,7 +3113,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(
|
||||
<< os_thread_pf(os_thread_get_curr_id());
|
||||
#endif /* UNIV_DEBUG_THREAD_CREATION */
|
||||
|
||||
-#ifdef UNIV_LINUX
|
||||
+#if defined(UNIV_LINUX) && defined(SET_PAGE_CLEANER_PRIORITY)
|
||||
/* linux might be able to set different setting for each thread.
|
||||
worth to try to set high priority for page cleaner threads */
|
||||
if (buf_flush_page_cleaner_set_priority(
|
||||
@@ -3126,7 +3126,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(
|
||||
" page cleaner thread priority can be changed."
|
||||
" See the man page of setpriority().";
|
||||
}
|
||||
-#endif /* UNIV_LINUX */
|
||||
+#endif /* UNIV_LINUX && SET_PAGE_CLEANER_PRIORITY */
|
||||
|
||||
buf_page_cleaner_is_active = true;
|
||||
|
||||
@@ -3481,7 +3481,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_worker)(
|
||||
page_cleaner->n_workers++;
|
||||
mutex_exit(&page_cleaner->mutex);
|
||||
|
||||
-#ifdef UNIV_LINUX
|
||||
+#if defined(UNIV_LINUX) && defined(SET_PAGE_CLEANER_PRIORITY)
|
||||
/* linux might be able to set different setting for each thread
|
||||
worth to try to set high priority for page cleaner threads */
|
||||
if (buf_flush_page_cleaner_set_priority(
|
||||
@@ -3490,7 +3490,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_worker)(
|
||||
ib::info() << "page_cleaner worker priority: "
|
||||
<< buf_flush_page_cleaner_priority;
|
||||
}
|
||||
-#endif /* UNIV_LINUX */
|
||||
+#endif /* UNIV_LINUX && SET_PAGE_CLEANER_PRIORITY */
|
||||
|
||||
while (true) {
|
||||
os_event_wait(page_cleaner->is_requested);
|
||||
diff --git a/storage/innobase/innodb.cmake b/storage/innobase/innodb.cmake
|
||||
index a90fe67f492..0d0a3ad7e3b 100644
|
||||
--- a/storage/innobase/innodb.cmake
|
||||
+++ b/storage/innobase/innodb.cmake
|
||||
@@ -38,6 +38,11 @@ IF(UNIX)
|
||||
LINK_LIBRARIES(aio)
|
||||
ENDIF()
|
||||
|
||||
+ OPTION(WITH_INNODB_PAGE_CLEANER_PRIORITY "Set a high priority for page cleaner threads" ON)
|
||||
+ IF(WITH_INNODB_PAGE_CLEANER_PRIORITY)
|
||||
+ ADD_DEFINITIONS("-DSET_PAGE_CLEANER_PRIORITY")
|
||||
+ ENDIF()
|
||||
+
|
||||
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||
ADD_DEFINITIONS("-DUNIV_SOLARIS")
|
||||
ENDIF()
|
12
build/install/snap/src/redis/bin/start-redis-server
Executable file
12
build/install/snap/src/redis/bin/start-redis-server
Executable file
@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
# shellcheck source=src/redis/utilities/redis-utilities
|
||||
. "$SNAP/utilities/redis-utilities"
|
||||
|
||||
mkdir -p "${SNAP_DATA}/redis"
|
||||
chmod 750 "${SNAP_DATA}/redis"
|
||||
|
||||
# redis doesn't support environment variables in its config files. Thankfully
|
||||
# it supports reading the config file from stdin though, so we'll rewrite the
|
||||
# config file on the fly and pipe it in.
|
||||
sed -e "s|\${SNAP_DATA}|$SNAP_DATA|;s|\${REDIS_PIDFILE}|$REDIS_PIDFILE|;s|\${REDIS_SOCKET}|$REDIS_SOCKET|" "$SNAP/config/redis/redis.conf" | redis-server -
|
1023
build/install/snap/src/redis/config/redis.conf
Normal file
1023
build/install/snap/src/redis/config/redis.conf
Normal file
File diff suppressed because it is too large
Load Diff
35
build/install/snap/src/redis/utilities/redis-utilities
Executable file
35
build/install/snap/src/redis/utilities/redis-utilities
Executable file
@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
|
||||
export REDIS_PIDFILE="/tmp/pids/redis.pid"
|
||||
export REDIS_SOCKET="/tmp/sockets/redis.sock"
|
||||
|
||||
mkdir -p "$(dirname "$REDIS_PIDFILE")"
|
||||
mkdir -p "$(dirname "$REDIS_SOCKET")"
|
||||
chmod 750 "$(dirname "$REDIS_PIDFILE")"
|
||||
chmod 750 "$(dirname "$REDIS_SOCKET")"
|
||||
|
||||
redis_is_running()
|
||||
{
|
||||
[ -f "$REDIS_PIDFILE" ] && [ -S "$REDIS_SOCKET" ]
|
||||
}
|
||||
|
||||
wait_for_redis()
|
||||
{
|
||||
if ! redis_is_running; then
|
||||
printf "Waiting for redis... "
|
||||
while ! redis_is_running; do
|
||||
sleep 1
|
||||
done
|
||||
printf "done\n"
|
||||
fi
|
||||
}
|
||||
|
||||
redis_pid()
|
||||
{
|
||||
if redis_is_running; then
|
||||
cat "$REDIS_PIDFILE"
|
||||
else
|
||||
echo "Unable to get redis PID as it's not yet running" >&2
|
||||
echo ""
|
||||
fi
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "asc-web-components",
|
||||
"version": "1.0.36",
|
||||
"version": "1.0.38",
|
||||
"description": "Ascensio System SIA component library",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "dist/asc-web-components.cjs.js",
|
||||
@ -33,6 +33,7 @@
|
||||
"prop-types": "^15.7.2",
|
||||
"rc-tree": "^2.1.2",
|
||||
"react-autosize-textarea": "^7.0.0",
|
||||
"react-avatar-edit": "^0.8.3",
|
||||
"react-custom-scrollbars": "^4.2.1",
|
||||
"react-datepicker": "^2.8.0",
|
||||
"react-lifecycles-compat": "^3.0.4",
|
||||
|
218
web/ASC.Web.Components/src/components/avatar-editor/index.js
Normal file
218
web/ASC.Web.Components/src/components/avatar-editor/index.js
Normal file
@ -0,0 +1,218 @@
|
||||
import React, { memo } from 'react'
|
||||
import styled, { css } from 'styled-components'
|
||||
import PropTypes from 'prop-types'
|
||||
import ModalDialog from '../modal-dialog'
|
||||
import Button from '../button'
|
||||
import { Text } from '../text'
|
||||
import Avatar from 'react-avatar-edit'
|
||||
import { default as ASCAvatar } from '../avatar/index'
|
||||
|
||||
const StyledASCAvatar = styled(ASCAvatar)`
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
`;
|
||||
const StyledAvatarContainer = styled.div`
|
||||
text-align: center;
|
||||
div:first-child {
|
||||
margin: 0 auto;
|
||||
}
|
||||
`;
|
||||
class AvatarEditorBody extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
croppedImage: null,
|
||||
src: this.props.image,
|
||||
hasMaxSizeError: false
|
||||
}
|
||||
this.onCrop = this.onCrop.bind(this)
|
||||
this.onClose = this.onClose.bind(this)
|
||||
this.onBeforeFileLoad = this.onBeforeFileLoad.bind(this)
|
||||
this.onFileLoad = this.onFileLoad.bind(this)
|
||||
|
||||
}
|
||||
onClose() {
|
||||
this.props.onCloseEditor();
|
||||
this.setState({ croppedImage: null })
|
||||
}
|
||||
onCrop(croppedImage) {
|
||||
this.props.onCropImage(croppedImage);
|
||||
this.setState({ croppedImage })
|
||||
}
|
||||
onBeforeFileLoad(elem) {
|
||||
if (elem.target.files[0].size > this.props.maxSize * 1000000) {
|
||||
this.setState({
|
||||
hasMaxSizeError: true
|
||||
});
|
||||
elem.target.value = "";
|
||||
}else if(this.state.hasMaxSizeError){
|
||||
this.setState({
|
||||
hasMaxSizeError: false
|
||||
});
|
||||
};
|
||||
}
|
||||
onFileLoad(file){
|
||||
let reader = new FileReader();
|
||||
let _this = this;
|
||||
reader.onloadend = () => {
|
||||
_this.props.onFileLoad(reader.result);
|
||||
};
|
||||
reader.readAsDataURL(file)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<StyledAvatarContainer>
|
||||
<Avatar
|
||||
width={400}
|
||||
height={295}
|
||||
imageWidth={400}
|
||||
cropRadius={50}
|
||||
onCrop={this.onCrop}
|
||||
onClose={this.onClose}
|
||||
onBeforeFileLoad={this.onBeforeFileLoad}
|
||||
onFileLoad={this.onFileLoad}
|
||||
label={this.props.label}
|
||||
src={this.state.src}
|
||||
/>
|
||||
{this.state.croppedImage && (
|
||||
<div>
|
||||
<StyledASCAvatar
|
||||
size='max'
|
||||
role='user'
|
||||
source={this.state.croppedImage}
|
||||
editing={false}
|
||||
/>
|
||||
<StyledASCAvatar
|
||||
size='big'
|
||||
role='user'
|
||||
source={this.state.croppedImage}
|
||||
editing={false}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
this.state.hasMaxSizeError &&
|
||||
<Text.Body as='span' color="#ED7309" isBold={true}>
|
||||
{this.props.maxSizeErrorLabel}
|
||||
</Text.Body>
|
||||
}
|
||||
</StyledAvatarContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarEditor extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
defaultImage: null,
|
||||
croppedImage: null,
|
||||
visible: props.value
|
||||
};
|
||||
|
||||
this.onClose = this.onClose.bind(this);
|
||||
|
||||
this.onCropImage = this.onCropImage.bind(this);
|
||||
this.onCloseEditor = this.onCloseEditor.bind(this);
|
||||
|
||||
this.onFileLoad = this.onFileLoad.bind(this);
|
||||
this.onSaveButtonClick = this.onSaveButtonClick.bind(this);
|
||||
|
||||
}
|
||||
onFileLoad(file){
|
||||
this.setState({ defaultImage: file });
|
||||
}
|
||||
onSaveButtonClick() {
|
||||
this.props.onSave({
|
||||
defaultImage: this.state.defaultImage,
|
||||
croppedImage: this.state.croppedImage
|
||||
});
|
||||
this.setState({ visible: false });
|
||||
}
|
||||
onCloseEditor() {
|
||||
this.setState({
|
||||
croppedImage: null
|
||||
});
|
||||
}
|
||||
onCropImage(result) {
|
||||
this.setState({
|
||||
croppedImage: result
|
||||
});
|
||||
}
|
||||
|
||||
onClose() {
|
||||
this.setState({ visible: false });
|
||||
this.props.onClose();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.props.visible !== prevProps.visible) {
|
||||
this.setState({ visible: this.props.visible });
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<ModalDialog
|
||||
visible={this.state.visible}
|
||||
headerContent={this.props.headerLabel}
|
||||
bodyContent={
|
||||
<AvatarEditorBody
|
||||
maxSize={this.props.maxSize}
|
||||
image={this.props.image}
|
||||
onCropImage={this.onCropImage}
|
||||
onCloseEditor={this.onCloseEditor}
|
||||
label={this.props.chooseFileLabel}
|
||||
maxSizeErrorLabel={this.props.maxSizeErrorLabel}
|
||||
onFileLoad={this.onFileLoad}
|
||||
/>
|
||||
}
|
||||
footerContent={[
|
||||
<Button
|
||||
key="SaveBtn"
|
||||
label={this.props.saveButtonLabel}
|
||||
primary={true}
|
||||
onClick={this.onSaveButtonClick}
|
||||
/>,
|
||||
<Button
|
||||
key="CancelBtn"
|
||||
label={this.props.cancelButtonLabel}
|
||||
onClick={this.onClose}
|
||||
style={{ marginLeft: "8px" }}
|
||||
/>
|
||||
]}
|
||||
onClose={this.props.onClose}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AvatarEditor.propTypes = {
|
||||
visible: PropTypes.bool,
|
||||
headerLabel: PropTypes.string,
|
||||
chooseFileLabel: PropTypes.string,
|
||||
saveButtonLabel: PropTypes.string,
|
||||
maxSizeErrorLabel: PropTypes.string,
|
||||
image: PropTypes.string,
|
||||
cancelButtonLabel: PropTypes.string,
|
||||
maxSize: PropTypes.number,
|
||||
|
||||
onSave: PropTypes.func,
|
||||
onClose: PropTypes.func
|
||||
};
|
||||
|
||||
AvatarEditor.defaultProps = {
|
||||
visible: false,
|
||||
maxSize: 1, //1MB
|
||||
chooseFileLabel: 'Choose a file',
|
||||
headerLabel: 'Edit Photo',
|
||||
saveButtonLabel: 'Save',
|
||||
cancelButtonLabel: 'Cancel',
|
||||
maxSizeErrorLabel: 'File is too big'
|
||||
};
|
||||
|
||||
export default AvatarEditor;
|
||||
|
||||
|
@ -56,7 +56,7 @@ const RoleWrapper = styled.div`
|
||||
`;
|
||||
|
||||
const ImageStyled = styled.img`
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 50%;
|
||||
|
||||
|
373
web/ASC.Web.Components/src/components/password-input/index.js
Normal file
373
web/ASC.Web.Components/src/components/password-input/index.js
Normal file
@ -0,0 +1,373 @@
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { tablet } from '../../utils/device';
|
||||
import InputBlock from '../input-block'
|
||||
import { Icons } from '../icons'
|
||||
import Link from '../link'
|
||||
import { Text } from '../text'
|
||||
import DropDown from '../drop-down'
|
||||
|
||||
const StyledInput = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 32px;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
@media ${tablet} {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
`;
|
||||
|
||||
const PasswordProgress = styled.div`
|
||||
${props => props.inputWidth ? `width: ${props.inputWidth};` : `flex: auto;`}
|
||||
`;
|
||||
|
||||
const NewPasswordButton = styled.div`
|
||||
margin-left: 16px;
|
||||
margin-top: -6px;
|
||||
`;
|
||||
|
||||
const CopyLink = styled.div`
|
||||
margin-top: -6px;
|
||||
margin-left: 16px;
|
||||
|
||||
@media ${tablet} {
|
||||
width: 100%;
|
||||
margin-left: 0px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
const Progress = styled.div`
|
||||
border: 3px solid ${props => (!props.isDisabled && props.progressColor) ? props.progressColor : 'transparent'};
|
||||
border-radius: 2px;
|
||||
margin-top: -4px;
|
||||
width: ${props => props.progressWidth ? props.progressWidth + '%' : '0%'};
|
||||
`;
|
||||
|
||||
const StyledTooltipContainer = styled(Text.Body)`
|
||||
margin: 8px 16px 16px 16px;
|
||||
`;
|
||||
|
||||
const StyledTooltipItem = styled(Text.Body)`
|
||||
margin-left: 8px;
|
||||
height: 24px;
|
||||
color: ${props => props.valid ? '#44bb00' : '#B40404'};
|
||||
`;
|
||||
|
||||
class PasswordInput extends React.PureComponent {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
type: props.inputType,
|
||||
progressColor: 'transparent',
|
||||
progressWidth: 0,
|
||||
inputValue: '',
|
||||
displayTooltip: false,
|
||||
validLength: false,
|
||||
validDigits: false,
|
||||
validCapital: false,
|
||||
validSpecial: false
|
||||
}
|
||||
}
|
||||
|
||||
onFocus = () => {
|
||||
this.setState({
|
||||
displayTooltip: true
|
||||
});
|
||||
}
|
||||
|
||||
onBlur = () => {
|
||||
this.setState({
|
||||
displayTooltip: false
|
||||
});
|
||||
}
|
||||
|
||||
changeInputType = () => {
|
||||
const newType = this.state.type === 'text' ? 'password' : 'text';
|
||||
|
||||
this.setState({
|
||||
type: newType
|
||||
});
|
||||
}
|
||||
|
||||
testStrength = value => {
|
||||
const { generatorSpecial, passwordSettings } = this.props;
|
||||
const specSymbols = new RegExp('[' + generatorSpecial + ']');
|
||||
|
||||
let capital;
|
||||
let digits;
|
||||
let special;
|
||||
|
||||
passwordSettings.upperCase
|
||||
? capital = /[A-Z]/.test(value)
|
||||
: capital = true;
|
||||
|
||||
passwordSettings.digits
|
||||
? digits = /\d/.test(value)
|
||||
: digits = true;
|
||||
|
||||
passwordSettings.specSymbols
|
||||
? special = specSymbols.test(value)
|
||||
: special = true;
|
||||
|
||||
return {
|
||||
digits: digits,
|
||||
capital: capital,
|
||||
special: special,
|
||||
length: value.length >= passwordSettings.minLength
|
||||
};
|
||||
}
|
||||
|
||||
checkPassword = (value) => {
|
||||
const greenColor = '#44bb00';
|
||||
const redColor = '#B40404';
|
||||
const passwordValidation = this.testStrength(value);
|
||||
const progressScore = passwordValidation.digits
|
||||
&& passwordValidation.capital
|
||||
&& passwordValidation.special
|
||||
&& passwordValidation.length;
|
||||
const progressWidth = value.length * 100 / this.props.passwordSettings.minLength;
|
||||
const progressColor = progressScore
|
||||
? greenColor
|
||||
: (value.length === 0)
|
||||
? 'transparent'
|
||||
: redColor;
|
||||
|
||||
this.setState({
|
||||
progressColor: progressColor,
|
||||
progressWidth: progressWidth > 100 ? 100 : progressWidth,
|
||||
inputValue: value,
|
||||
validLength: passwordValidation.length,
|
||||
validDigits: passwordValidation.digits,
|
||||
validCapital: passwordValidation.capital,
|
||||
validSpecial: passwordValidation.special
|
||||
});
|
||||
}
|
||||
|
||||
onChangeAction = (e) => {
|
||||
this.props.onChange && this.props.onChange(e);
|
||||
this.checkPassword(e.target.value);
|
||||
}
|
||||
|
||||
onGeneratePassword = (e) => {
|
||||
if (this.props.isDisabled)
|
||||
return e.preventDefault();
|
||||
|
||||
const newPassword = this.getNewPassword();
|
||||
this.checkPassword(newPassword);
|
||||
}
|
||||
|
||||
getNewPassword = () => {
|
||||
const { passwordSettings, generatorSpecial } = this.props;
|
||||
|
||||
const length = passwordSettings.minLength;
|
||||
const string = 'abcdefghijklmnopqrstuvwxyz';
|
||||
const numeric = '0123456789';
|
||||
const special = generatorSpecial;
|
||||
|
||||
let password = '';
|
||||
let character = '';
|
||||
|
||||
while (password.length < length) {
|
||||
const a = Math.ceil(string.length * Math.random() * Math.random());
|
||||
const b = Math.ceil(numeric.length * Math.random() * Math.random());
|
||||
const c = Math.ceil(special.length * Math.random() * Math.random());
|
||||
|
||||
let hold = string.charAt(a);
|
||||
|
||||
if (passwordSettings.upperCase) {
|
||||
hold = (password.length % 2 == 0)
|
||||
? (hold.toUpperCase())
|
||||
: (hold);
|
||||
}
|
||||
|
||||
character += hold;
|
||||
|
||||
if (passwordSettings.digits) {
|
||||
character += numeric.charAt(b);
|
||||
}
|
||||
|
||||
if (passwordSettings.specSymbols) {
|
||||
character += special.charAt(c);
|
||||
}
|
||||
|
||||
password = character;
|
||||
}
|
||||
|
||||
password = password
|
||||
.split('')
|
||||
.sort(() => 0.5 - Math.random())
|
||||
.join('');
|
||||
|
||||
return password.substr(0, length);
|
||||
}
|
||||
|
||||
copyToClipboard = emailInputName => {
|
||||
const { clipEmailResource, clipPasswordResource, isDisabled } = this.props;
|
||||
|
||||
if (isDisabled)
|
||||
return event.preventDefault();
|
||||
|
||||
const textField = document.createElement('textarea');
|
||||
const emailValue = document.getElementsByName(emailInputName)[0].value;
|
||||
|
||||
textField.innerText = clipEmailResource + emailValue + ' | ' + clipPasswordResource + this.state.inputValue;
|
||||
|
||||
document.body.appendChild(textField);
|
||||
textField.select();
|
||||
document.execCommand('copy');
|
||||
textField.remove();
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
inputName,
|
||||
isDisabled,
|
||||
scale,
|
||||
size,
|
||||
clipActionResource,
|
||||
tooltipPasswordTitle,
|
||||
tooltipPasswordLength,
|
||||
tooltipPasswordDigits,
|
||||
tooltipPasswordCapital,
|
||||
tooltipPasswordSpecial,
|
||||
emailInputName,
|
||||
inputWidth,
|
||||
passwordSettings
|
||||
} = this.props;
|
||||
const {
|
||||
type,
|
||||
progressColor,
|
||||
progressWidth,
|
||||
inputValue,
|
||||
validLength,
|
||||
validDigits,
|
||||
validCapital,
|
||||
validSpecial,
|
||||
displayTooltip
|
||||
} = this.state;
|
||||
|
||||
const iconsColor = isDisabled ? '#D0D5DA' : '#A3A9AE';
|
||||
|
||||
const tooltipContent = (
|
||||
<StyledTooltipContainer forwardedAs='div' title={tooltipPasswordTitle}>
|
||||
{tooltipPasswordTitle}
|
||||
<StyledTooltipItem forwardedAs='div' title={tooltipPasswordLength} valid={validLength} >
|
||||
{tooltipPasswordLength}
|
||||
</StyledTooltipItem>
|
||||
{passwordSettings.digits &&
|
||||
<StyledTooltipItem forwardedAs='div' title={tooltipPasswordDigits} valid={validDigits} >
|
||||
{tooltipPasswordDigits}
|
||||
</StyledTooltipItem>
|
||||
}
|
||||
{passwordSettings.upperCase &&
|
||||
<StyledTooltipItem forwardedAs='div' title={tooltipPasswordCapital} valid={validCapital} >
|
||||
{tooltipPasswordCapital}
|
||||
</StyledTooltipItem>
|
||||
}
|
||||
{passwordSettings.specSymbols &&
|
||||
<StyledTooltipItem forwardedAs='div' title={tooltipPasswordSpecial} valid={validSpecial} >
|
||||
{tooltipPasswordSpecial}
|
||||
</StyledTooltipItem>
|
||||
}
|
||||
</StyledTooltipContainer>
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledInput>
|
||||
<PasswordProgress inputWidth={inputWidth}>
|
||||
<InputBlock
|
||||
name={inputName}
|
||||
hasError={false}
|
||||
isDisabled={isDisabled}
|
||||
iconName='EyeIcon'
|
||||
value={inputValue}
|
||||
onIconClick={this.changeInputType}
|
||||
onChange={this.onChangeAction}
|
||||
scale={scale}
|
||||
size={size}
|
||||
type={type}
|
||||
iconColor={iconsColor}
|
||||
isIconFill={true}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
>
|
||||
{displayTooltip &&
|
||||
<DropDown directionY='top' manualY='150%' isOpen={true}>
|
||||
{tooltipContent}
|
||||
</DropDown>
|
||||
}
|
||||
</InputBlock>
|
||||
<Progress progressColor={progressColor} progressWidth={progressWidth} isDisabled={isDisabled} />
|
||||
</PasswordProgress>
|
||||
<NewPasswordButton>
|
||||
<Icons.RefreshIcon
|
||||
size="medium"
|
||||
color={iconsColor}
|
||||
isfill={true}
|
||||
onClick={this.onGeneratePassword}
|
||||
/>
|
||||
</NewPasswordButton>
|
||||
<CopyLink>
|
||||
<Link
|
||||
type="action"
|
||||
isHovered={true}
|
||||
fontSize={13}
|
||||
color={iconsColor}
|
||||
onClick={this.copyToClipboard.bind(this, emailInputName)}
|
||||
>
|
||||
{clipActionResource}
|
||||
</Link>
|
||||
</CopyLink>
|
||||
</StyledInput>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
PasswordInput.propTypes = {
|
||||
inputType: PropTypes.oneOf(['text', 'password']),
|
||||
inputName: PropTypes.string,
|
||||
emailInputName: PropTypes.string.isRequired,
|
||||
inputValue: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
|
||||
isDisabled: PropTypes.bool,
|
||||
size: PropTypes.oneOf(['base', 'middle', 'big', 'huge']),
|
||||
scale: PropTypes.bool,
|
||||
|
||||
clipActionResource: PropTypes.string,
|
||||
clipEmailResource: PropTypes.string,
|
||||
clipPasswordResource: PropTypes.string,
|
||||
|
||||
tooltipPasswordTitle: PropTypes.string,
|
||||
tooltipPasswordLength: PropTypes.string,
|
||||
tooltipPasswordDigits: PropTypes.string,
|
||||
tooltipPasswordCapital: PropTypes.string,
|
||||
tooltipPasswordSpecial: PropTypes.string,
|
||||
|
||||
generatorSpecial: PropTypes.string,
|
||||
passwordSettings: PropTypes.object.isRequired
|
||||
|
||||
}
|
||||
|
||||
PasswordInput.defaultProps = {
|
||||
inputType: 'password',
|
||||
inputName: 'passwordInput',
|
||||
|
||||
size: 'base',
|
||||
scale: true,
|
||||
|
||||
clipEmailResource: 'E-mail',
|
||||
clipPasswordResource: 'Password',
|
||||
|
||||
generatorSpecial: '!@#$%^&*'
|
||||
|
||||
}
|
||||
|
||||
export default PasswordInput;
|
@ -11,6 +11,7 @@ export { default as GroupButtonsMenu } from './components/group-buttons-menu'
|
||||
export { default as TreeMenu } from './components/tree-menu'
|
||||
export { default as TreeNode } from './components/tree-menu-node'
|
||||
export { default as Avatar } from './components/avatar'
|
||||
export { default as AvatarEditor } from './components/avatar-editor'
|
||||
export { default as RequestLoader } from './components/request-loader'
|
||||
export { default as MainButton } from './components/main-button'
|
||||
export { default as ContextMenuButton } from './components/context-menu-button'
|
||||
@ -54,3 +55,4 @@ export { default as RowContainer } from './components/row-container'
|
||||
export { default as FieldContainer } from './components/field-container'
|
||||
export { default as utils } from './utils'
|
||||
export { default as DatePicker } from './components/calendar-new/date-input'
|
||||
export { default as PasswordInput } from './components/password-input'
|
||||
|
@ -4976,6 +4976,11 @@ kind-of@^6.0.0, kind-of@^6.0.2:
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
|
||||
integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
|
||||
|
||||
konva@2.5.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/konva/-/konva-2.5.1.tgz#cca611a9522e831e54cf57c508a1aed3f0ceac25"
|
||||
integrity sha512-YdHEWqmbWPieqIZuLx7JFGm9Ui08hSUaSJ2k2Ml8o5giFgJ0WmxAS0DPXIM+Ty2ADRagOHZfXSJ/skwYqqlwgQ==
|
||||
|
||||
lazy-cache@^0.2.3:
|
||||
version "0.2.7"
|
||||
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-0.2.7.tgz#7feddf2dcb6edb77d11ef1d117ab5ffdf0ab1b65"
|
||||
@ -6777,6 +6782,13 @@ react-autosize-textarea@^7.0.0:
|
||||
line-height "^0.3.1"
|
||||
prop-types "^15.5.6"
|
||||
|
||||
react-avatar-edit@^0.8.3:
|
||||
version "0.8.3"
|
||||
resolved "https://registry.yarnpkg.com/react-avatar-edit/-/react-avatar-edit-0.8.3.tgz#0ebf21391328fc255429bdfbc782f795827109bf"
|
||||
integrity sha512-QEedh6DjDCSI7AUsUHHtfhxApCWC5hJAoywxUA5PtUdw03iIjEurgVqPOIt1UBHhU/Zk/9amElRF3oepN9JZSg==
|
||||
dependencies:
|
||||
konva "2.5.1"
|
||||
|
||||
react-custom-scrollbars@^4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz#830fd9502927e97e8a78c2086813899b2a8b66db"
|
||||
|
34
web/ASC.Web.Storybook/stories/avatar-editor/README.md
Normal file
34
web/ASC.Web.Storybook/stories/avatar-editor/README.md
Normal file
@ -0,0 +1,34 @@
|
||||
# Avatar Editor
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import { AvatarEditor } from 'asc-web-components';
|
||||
```
|
||||
|
||||
#### Description
|
||||
|
||||
Required to display user avatar editor on page.
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
<AvatarEditor
|
||||
visible={true}
|
||||
onSave={(data) =>{console.log(data.croppedImage, data.defaultImage)}}
|
||||
/>
|
||||
```
|
||||
|
||||
#### Properties
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ------------------ | -------- | :------: | ----------------------------------------- | ------------------ | ----------------------------------------------------- |
|
||||
| `visible` | `bool` | - | | `false` | Display avatar editor or not |
|
||||
| `chooseFileLabel` | `string` | - | | `Choose a file` | |
|
||||
| `headerLabel` | `string` | - | | `Edit Photo` | |
|
||||
| `saveButtonLabel` | `string` | - | | `Save` | |
|
||||
| `cancelButtonLabel` | `string` | - | | `Cancel` | |
|
||||
| `maxSizeErrorLabel` | `string` | - | | `File is too big` | |
|
||||
| `maxSize` | `number` | - | | `1` | Max size of image |
|
||||
| `onSave` | `function` | - | | | |
|
||||
| `onClose` | `function` | - | | | |
|
72
web/ASC.Web.Storybook/stories/avatar-editor/index.stories.js
Normal file
72
web/ASC.Web.Storybook/stories/avatar-editor/index.stories.js
Normal file
@ -0,0 +1,72 @@
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { withKnobs, boolean, text, select } from '@storybook/addon-knobs/react';
|
||||
import withReadme from 'storybook-readme/with-readme';
|
||||
import Readme from './README.md';
|
||||
import { AvatarEditor, Avatar } from 'asc-web-components';
|
||||
import Section from '../../.storybook/decorators/section';
|
||||
|
||||
class AvatarEditorStory extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
isOpen: false,
|
||||
userImage: null
|
||||
}
|
||||
|
||||
this.openEditor = this.openEditor.bind(this);
|
||||
this.onClose = this.onClose.bind(this);
|
||||
this.onSave = this.onSave.bind(this);
|
||||
|
||||
}
|
||||
onSave(result){
|
||||
action('onSave')(result);
|
||||
this.setState({
|
||||
userImage: result.croppedImage,
|
||||
isOpen: false
|
||||
})
|
||||
}
|
||||
openEditor(){
|
||||
this.setState({
|
||||
isOpen: true
|
||||
})
|
||||
}
|
||||
onClose(){
|
||||
action('onClose');
|
||||
this.setState({
|
||||
isOpen: false
|
||||
})
|
||||
}
|
||||
render(){
|
||||
return(
|
||||
<div>
|
||||
<Avatar
|
||||
size='max'
|
||||
role='user'
|
||||
source={this.state.userImage }
|
||||
editing={true}
|
||||
editAction={this.openEditor}
|
||||
/>
|
||||
<AvatarEditor
|
||||
visible={this.state.isOpen}
|
||||
onClose={this.onClose}
|
||||
onSave={this.onSave}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
storiesOf('Components|AvatarEditor', module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add('avatar editor', () => {
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<AvatarEditorStory />
|
||||
</Section>
|
||||
);
|
||||
});
|
78
web/ASC.Web.Storybook/stories/input/password/README.md
Normal file
78
web/ASC.Web.Storybook/stories/input/password/README.md
Normal file
@ -0,0 +1,78 @@
|
||||
# PasswordInput
|
||||
|
||||
#### Description
|
||||
|
||||
Password entry field with advanced capabilities for displaying, validation of correspondence and generation based on settings.
|
||||
|
||||
Object with settings:
|
||||
|
||||
```js
|
||||
{
|
||||
minLength: 6,
|
||||
upperCase: false,
|
||||
digits: false,
|
||||
specSymbols: false
|
||||
}
|
||||
```
|
||||
|
||||
Check for compliance with settings is carried out on fly. As you type in required number of characters, progress bar will fill up and when all conditions are met, the color will change from red to green.
|
||||
|
||||
Depending on screen width of device, input will change location of elements.
|
||||
|
||||
When setting focus to input, tooltip will be shown with progress in fulfilling conditions specified in settings. When unfocused, tooltip disappears.
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
import { PasswordInput } from "asc-web-components";
|
||||
|
||||
const settings = {
|
||||
minLength: 6,
|
||||
upperCase: false,
|
||||
digits: false,
|
||||
specSymbols: false
|
||||
};
|
||||
|
||||
<PasswordInput
|
||||
inputName="demoPasswordInput"
|
||||
emailInputName="demoEmailInput"
|
||||
inputValue={value}
|
||||
onChange={e => {
|
||||
set(e.target.value);
|
||||
}}
|
||||
clipActionResource="Copy e-mail and password"
|
||||
clipEmailResource="E-mail: "
|
||||
clipPasswordResource="Password: "
|
||||
tooltipPasswordTitle="Password must contain:"
|
||||
tooltipPasswordLength="from 6 to 30 characters"
|
||||
tooltipPasswordDigits="digits"
|
||||
tooltipPasswordCapital="capital letters"
|
||||
tooltipPasswordSpecial="special characters (!@#$%^&*)"
|
||||
generatorSpecial="!@#$%^&*"
|
||||
passwordSettings={settings}
|
||||
isDisabled={false}
|
||||
/>;
|
||||
```
|
||||
|
||||
#### Properties
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ------------------- | --------- | :------: | ------------------ | --------- | --------------------------------------------------------- |
|
||||
| `inputType` | `array` | - | `text`, `password` | `password`| It is necessary for correct display of values inside input|
|
||||
| `inputName` | `string` | - | - | `passwordInput`| Input name |
|
||||
| `emailInputName` | `string` | ✅ | - | - | Required to associate password field with email field |
|
||||
| `inputValue` | `string` | - | - | - | Input value |
|
||||
| `onChange` | `func` | - | - | - | Will be triggered whenever an PasswordInput typing |
|
||||
| `clipActionResource`| `string` | - | - | - | Translation of text for copying email data and password |
|
||||
| `clipEmailResource` | `string` | - | - | `E-mail` | Text translation email to copy |
|
||||
| `clipPasswordResource`| `string` | - | - | `Password`| Text translation password to copy |
|
||||
| `tooltipPasswordTitle`| `string` | - | - | - | Text translation tooltip |
|
||||
| `tooltipPasswordLength`| `string` | - | - | - | Password text translation is long tooltip |
|
||||
| `tooltipPasswordDigits`| `string` | - | - | - | Digit text translation tooltip |
|
||||
| `tooltipPasswordCapital`| `string` |- | - | - | Capital text translation tooltip |
|
||||
| `tooltipPasswordSpecial`| `string` |- | - | - | Special text translation tooltip |
|
||||
| `generatorSpecial` | `string` | - | - | `!@#$%^&*`| Set of special characters for password generator and validator|
|
||||
| `passwordSettings` | `object` | ✅ | - | - | Set of settings for password generator and validator |
|
||||
| `isDisabled` | `bool` | - | - | `false` | Set input disabled |
|
||||
| `inputWidth` | `string` | - | - | - | If you need to set input width manually |
|
||||
|
@ -0,0 +1,66 @@
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { StringValue } from 'react-values';
|
||||
import { withKnobs, boolean, text, select, number } from '@storybook/addon-knobs/react';
|
||||
import withReadme from 'storybook-readme/with-readme';
|
||||
import Readme from './README.md';
|
||||
import { PasswordInput, TextInput } from 'asc-web-components';
|
||||
import Section from '../../../.storybook/decorators/section';
|
||||
|
||||
storiesOf('Components|Input', module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add('advanced password', () => {
|
||||
const isDisabled = boolean('isDisabled', false);
|
||||
const settingsUpperCase = boolean('settingsUpperCase', false);
|
||||
const settingsDigits = boolean('settingsDigits', false);
|
||||
const settingsSpecSymbols = boolean('settingsSpecSymbols', false);
|
||||
|
||||
const fakeSettings = {
|
||||
minLength: 6,
|
||||
upperCase: settingsUpperCase,
|
||||
digits: settingsDigits,
|
||||
specSymbols: settingsSpecSymbols
|
||||
};
|
||||
|
||||
const tooltipPasswordLength = 'from ' + fakeSettings.minLength + ' to 30 characters';
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<div style={{height: '110px'}}></div>
|
||||
<TextInput
|
||||
name='demoEmailInput'
|
||||
size='base'
|
||||
isDisabled={isDisabled}
|
||||
isReadOnly={true}
|
||||
scale={true}
|
||||
value='demo@gmail.com'
|
||||
/>
|
||||
<br />
|
||||
<StringValue>
|
||||
{({ value, set }) => (
|
||||
<PasswordInput
|
||||
inputName='demoPasswordInput'
|
||||
emailInputName='demoEmailInput'
|
||||
inputValue={value}
|
||||
onChange={e => {
|
||||
set(e.target.value);
|
||||
}}
|
||||
clipActionResource='Copy e-mail and password'
|
||||
clipEmailResource='E-mail: '
|
||||
clipPasswordResource='Password: '
|
||||
tooltipPasswordTitle='Password must contain:'
|
||||
tooltipPasswordLength={tooltipPasswordLength}
|
||||
tooltipPasswordDigits='digits'
|
||||
tooltipPasswordCapital='capital letters'
|
||||
tooltipPasswordSpecial='special characters (!@#$%^&*)'
|
||||
generatorSpecial='!@#$%^&*'
|
||||
passwordSettings={fakeSettings}
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
)}
|
||||
</StringValue>
|
||||
</Section>
|
||||
)
|
||||
});
|
Loading…
Reference in New Issue
Block a user