From 00a5b9d62b366fedfeff73acbb41d239aac50b57 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Sun, 26 Nov 2023 07:22:47 -0400 Subject: [PATCH 01/54] Initial file reorganisation --- spk/ffsync/{ => src/TO_REMOVE}/BROKEN | 0 spk/ffsync/src/{conf => TO_REMOVE}/PKG_DEPS | 0 spk/ffsync/src/{ => TO_REMOVE}/dsm-control.sh | 0 spk/ffsync/src/{ => TO_REMOVE}/ffsync.ini | 0 spk/ffsync/src/{ => TO_REMOVE}/ffsync.sc | 0 spk/ffsync/src/{ => TO_REMOVE}/installer.sh | 0 spk/ffsync/src/ffsync.png | Bin 13090 -> 64008 bytes spk/ffsync/src/requirements.txt | 80 ++++-------------- 8 files changed, 17 insertions(+), 63 deletions(-) rename spk/ffsync/{ => src/TO_REMOVE}/BROKEN (100%) rename spk/ffsync/src/{conf => TO_REMOVE}/PKG_DEPS (100%) rename spk/ffsync/src/{ => TO_REMOVE}/dsm-control.sh (100%) rename spk/ffsync/src/{ => TO_REMOVE}/ffsync.ini (100%) rename spk/ffsync/src/{ => TO_REMOVE}/ffsync.sc (100%) rename spk/ffsync/src/{ => TO_REMOVE}/installer.sh (100%) mode change 100755 => 100644 spk/ffsync/src/ffsync.png diff --git a/spk/ffsync/BROKEN b/spk/ffsync/src/TO_REMOVE/BROKEN similarity index 100% rename from spk/ffsync/BROKEN rename to spk/ffsync/src/TO_REMOVE/BROKEN diff --git a/spk/ffsync/src/conf/PKG_DEPS b/spk/ffsync/src/TO_REMOVE/PKG_DEPS similarity index 100% rename from spk/ffsync/src/conf/PKG_DEPS rename to spk/ffsync/src/TO_REMOVE/PKG_DEPS diff --git a/spk/ffsync/src/dsm-control.sh b/spk/ffsync/src/TO_REMOVE/dsm-control.sh similarity index 100% rename from spk/ffsync/src/dsm-control.sh rename to spk/ffsync/src/TO_REMOVE/dsm-control.sh diff --git a/spk/ffsync/src/ffsync.ini b/spk/ffsync/src/TO_REMOVE/ffsync.ini similarity index 100% rename from spk/ffsync/src/ffsync.ini rename to spk/ffsync/src/TO_REMOVE/ffsync.ini diff --git a/spk/ffsync/src/ffsync.sc b/spk/ffsync/src/TO_REMOVE/ffsync.sc similarity index 100% rename from spk/ffsync/src/ffsync.sc rename to spk/ffsync/src/TO_REMOVE/ffsync.sc diff --git a/spk/ffsync/src/installer.sh b/spk/ffsync/src/TO_REMOVE/installer.sh similarity index 100% rename from spk/ffsync/src/installer.sh rename to spk/ffsync/src/TO_REMOVE/installer.sh diff --git a/spk/ffsync/src/ffsync.png b/spk/ffsync/src/ffsync.png old mode 100755 new mode 100644 index afcbbfbbe26e7e7895f725e836976acd11dd38ee..ad08b0908c313fd69b541919f4e5344234ce8939 GIT binary patch literal 64008 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 literal 13090 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 Date: Sun, 26 Nov 2023 16:36:23 -0400 Subject: [PATCH 02/54] Include syncstorage-rs source --- cross/ffsync/Makefile | 18 +++++++++++++++++ cross/ffsync/digests | 3 +++ spk/ffsync/Makefile | 45 ++++++++++++++++++++----------------------- 3 files changed, 42 insertions(+), 24 deletions(-) create mode 100644 cross/ffsync/Makefile create mode 100644 cross/ffsync/digests diff --git a/cross/ffsync/Makefile b/cross/ffsync/Makefile new file mode 100644 index 00000000000..09b9b33dfa8 --- /dev/null +++ b/cross/ffsync/Makefile @@ -0,0 +1,18 @@ +PKG_NAME = ffsync +REPO_NAME = syncstorage-rs +PKG_VERS = 0.14.1 +PKG_EXT = tar.gz +PKG_DIST_NAME = $(REPO_NAME)-$(PKG_VERS).$(PKG_EXT) +PKG_DIST_SITE = https://github.com/mozilla-services/$(REPO_NAME)/archive +PKG_DIR = $(PKG_NAME)-$(PKG_VERS) + +DEPENDS = + +# powerpc archs (except qoriq) are not supported +UNSUPPORTED_ARCHS += $(OLD_PPC_ARCHS) + +HOMEPAGE = https://github.com/mozilla-services/syncstorage-rs/ +COMMENT = Mozilla Sync Storage built with Rust. +LICENSE = https://github.com/mozilla-services/syncstorage-rs/blob/master/LICENSE + +include ../../mk/spksrc.cross-rust.mk diff --git a/cross/ffsync/digests b/cross/ffsync/digests new file mode 100644 index 00000000000..4be5997e9b8 --- /dev/null +++ b/cross/ffsync/digests @@ -0,0 +1,3 @@ +syncstorage-rs-0.14.1.tar.gz SHA1 2b4fd69655caf646bed046fcc85db4ef844f0746 +syncstorage-rs-0.14.1.tar.gz SHA256 224d8c4af114b0af4eebd90decef951a08dde1204c13caada416347aa5ebe35c +syncstorage-rs-0.14.1.tar.gz MD5 de9034fc2fcc5bcbccf9df5c0e86f405 diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index 82b59c4f1ca..d8c7b0b40a4 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -1,38 +1,40 @@ SPK_NAME = ffsync -SPK_VERS = 1.5.2 -SPK_REV = 3 +SPK_VERS = 0.14.1 +SPK_REV = 4 SPK_ICON = src/ffsync.png -BETA = 1 -BUILD_DEPENDS = cross/python2 cross/setuptools_py2 cross/pip_py2 cross/wheel -BUILD_DEPENDS += cross/gevent cross/greenlet cross/cffi +BUILD_DEPENDS = cross/curl cross/mysql-connector-c +DEPENDS = cross/ffsync -DEPENDS = cross/busybox +PYTHON_PACKAGE = python311 WHEELS = src/requirements.txt +REQUIRED_MIN_DSM = 6.0 +SPK_DEPENDS = MariaDB10:python311 + MAINTAINER = SynoCommunity DESCRIPTION = Firefox Sync Server 1.5, used for Firefox 29 and later. You can use Firefox Sync Server to synchronize your bookmarks, passwords, settings, history, add-ons and tabs with Firefox on other computers. The service runs on port 8132. DISPLAY_NAME = Firefox Sync Server 1.5 -CHANGELOG = "1. Fix Python requirement
2. Fix startup issue when pidfile is not yet written" +CHANGELOG = "1. Upgrade to Mozilla Sync Storage built with Rust." -HOMEPAGE = https://docs.services.mozilla.com/howtos/run-sync-1.5.html -LICENSE = MPL/GPL/LGPL +HOMEPAGE = https://mozilla-services.readthedocs.io/en/latest/howtos/run-sync-1.5.html +LICENSE = MPL-2.0 HELPURL = https://github.com/SynoCommunity/spksrc/wiki/Firefox-Sync-Server-1.5 -INSTALLER_SCRIPT = src/installer.sh -SSS_SCRIPT = src/dsm-control.sh -FWPORTS = src/${SPK_NAME}.sc -CONF_DIR = src/conf/ +WIZARDS_DIR = src/wizard/ -INSTALL_DEP_SERVICES = mysql -START_DEP_SERVICES = mysql +STARTABLE = yes +SERVICE_USER = auto +SERVICE_SETUP = src/service-setup.sh +SERVICE_PORT = 8132 +SERVICE_PORT_TITLE = $(DISPLAY_NAME) -INSTALL_PREFIX = /usr/local/$(SPK_NAME) +# Admin link for in DSM UI +ADMIN_PORT = $(SERVICE_PORT) -POST_STRIP_TARGET = ffsync_extra_install +CONF_DIR = src/conf/ -BUSYBOX_CONFIG = usermng -ENV += BUSYBOX_CONFIG="$(BUSYBOX_CONFIG)" +POST_STRIP_TARGET = ffsync_extra_install include ../../mk/spksrc.spk.mk @@ -40,8 +42,3 @@ include ../../mk/spksrc.spk.mk ffsync_extra_install: install -m 755 -d $(STAGING_DIR)/var install -m 644 src/ffsync.ini $(STAGING_DIR)/var/ - sed -i -e "s|https://github.com/mozilla-services/mozservices/archive/e00e1b68130423ad98d0f6185655bde650443da8.zip|mozsvc==0.8|g" \ - -e "s|https://github.com/mozilla-services/tokenserver/archive/d7e513e8a4f5c588b70d685a8df1d2e508c341c0.zip|tokenserver==1.2.7|g" \ - -e "s|https://github.com/mozilla-services/server-syncstorage/archive/1.5.5.zip|SyncStorage==1.5.5|g" \ - -e "s|https://github.com/mozilla-services/syncserver/archive/1.5.2.tar.gz|syncserver==1.5.2|g" \ - $(STAGING_DIR)/share/wheelhouse/requirements.txt From f016cfa9f06b25ea5b19d44b811acb6cd014d5c5 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Mon, 27 Nov 2023 08:52:23 -0400 Subject: [PATCH 03/54] Migrate service scripts --- spk/ffsync/src/service-setup.sh | 103 ++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 spk/ffsync/src/service-setup.sh diff --git a/spk/ffsync/src/service-setup.sh b/spk/ffsync/src/service-setup.sh new file mode 100644 index 00000000000..6391277842d --- /dev/null +++ b/spk/ffsync/src/service-setup.sh @@ -0,0 +1,103 @@ +PYTHON_DIR="/var/packages/python311/target/bin" +PATH="${SYNOPKG_PKGDEST}/env/bin:${SYNOPKG_PKGDEST}/bin:${PYTHON_DIR}:${PATH}" +MARIADB_10_INSTALL_DIRECTORY="/var/packages/MariaDB10" +MARIADB_10_BIN_DIRECTORY="${MARIADB_10_INSTALL_DIRECTORY}/target/usr/local/mariadb10/bin" +MYSQL="${MARIADB_10_BIN_DIRECTORY}/mysql" + +PYTHON="${SYNOPKG_PKGDEST}/env/bin/python3" +SYNCSERVER="${HOME}/bin/syncserver" +HOME="${SYNOPKG_PKGDEST}/share/${SPK_NAME}" +CFG_FILE="${HOME}/config/local.toml" + +SERVICE_COMMAND="${SYNCSERVER} --config=${CFG_FILE}" + +service_preinst () +{ + # Check MySQL database + if [ "${SYNOPKG_PKG_STATUS}" = "INSTALL" ]; then + if [ -n "${wizard_mysql_password_root}" ]; then + if ! ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e quit > /dev/null 2>&1; then + echo "Incorrect MySQL root password" + exit 1 + fi + if ${MYSQL} -u root -p"${wizard_mysql_password_root}" mysql -e "SELECT User FROM user" | grep ^${SPK_NAME}$ > /dev/null 2>&1; then + echo "MySQL user ${SPK_NAME} already exists" + exit 1 + fi + if ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e "SHOW DATABASES" | grep -E '^(syncstorage_rs|tokenserver_rs)$' > /dev/null 2>&1; then + echo "MySQL database(s) for ${SPK_NAME} already exist(s)" + exit 1 + fi + fi + fi +} + +service_postinst () +{ + # Create a Python virtualenv + install_python_virtualenv + + # Install wheels + install_python_wheels + + if [ "${SYNOPKG_PKG_STATUS}" = "INSTALL" ]; then + # login as root sql user using whatever creds you set up for that + # this sets up a user for sync storage and sets up the databases + ${MYSQL} -u root -p ${wizard_mysql_password_root} < ${CFG_FILE} < Date: Mon, 27 Nov 2023 11:41:04 -0400 Subject: [PATCH 04/54] Fix repo download path --- cross/ffsync/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cross/ffsync/Makefile b/cross/ffsync/Makefile index 09b9b33dfa8..d0eefd5bee2 100644 --- a/cross/ffsync/Makefile +++ b/cross/ffsync/Makefile @@ -3,7 +3,7 @@ REPO_NAME = syncstorage-rs PKG_VERS = 0.14.1 PKG_EXT = tar.gz PKG_DIST_NAME = $(REPO_NAME)-$(PKG_VERS).$(PKG_EXT) -PKG_DIST_SITE = https://github.com/mozilla-services/$(REPO_NAME)/archive +PKG_DIST_SITE = https://github.com/mozilla-services/$(REPO_NAME)/archive/${PKG_VERS} PKG_DIR = $(PKG_NAME)-$(PKG_VERS) DEPENDS = From 8e9f71395ad3fa7e6d38b1a6a709b970187c644e Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Mon, 27 Nov 2023 14:21:26 -0400 Subject: [PATCH 05/54] Fix package name --- cross/{ffsync => syncstorage-rs}/Makefile | 7 +++---- cross/{ffsync => syncstorage-rs}/digests | 0 spk/ffsync/Makefile | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) rename cross/{ffsync => syncstorage-rs}/Makefile (68%) rename cross/{ffsync => syncstorage-rs}/digests (100%) diff --git a/cross/ffsync/Makefile b/cross/syncstorage-rs/Makefile similarity index 68% rename from cross/ffsync/Makefile rename to cross/syncstorage-rs/Makefile index d0eefd5bee2..0527ec4da84 100644 --- a/cross/ffsync/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -1,9 +1,8 @@ -PKG_NAME = ffsync -REPO_NAME = syncstorage-rs +PKG_NAME = syncstorage-rs PKG_VERS = 0.14.1 PKG_EXT = tar.gz -PKG_DIST_NAME = $(REPO_NAME)-$(PKG_VERS).$(PKG_EXT) -PKG_DIST_SITE = https://github.com/mozilla-services/$(REPO_NAME)/archive/${PKG_VERS} +PKG_DIST_NAME = $(PKG_NAME)-$(PKG_VERS).$(PKG_EXT) +PKG_DIST_SITE = https://github.com/mozilla-services/$(PKG_NAME)/archive/${PKG_VERS} PKG_DIR = $(PKG_NAME)-$(PKG_VERS) DEPENDS = diff --git a/cross/ffsync/digests b/cross/syncstorage-rs/digests similarity index 100% rename from cross/ffsync/digests rename to cross/syncstorage-rs/digests diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index d8c7b0b40a4..fc0024faf43 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -4,7 +4,7 @@ SPK_REV = 4 SPK_ICON = src/ffsync.png BUILD_DEPENDS = cross/curl cross/mysql-connector-c -DEPENDS = cross/ffsync +DEPENDS = cross/syncstorage-rs PYTHON_PACKAGE = python311 WHEELS = src/requirements.txt From 16da8d9ef68001c5e2720fd7f149b6dd6dae290f Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Mon, 27 Nov 2023 15:02:17 -0400 Subject: [PATCH 06/54] Fix rust build args --- cross/syncstorage-rs/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 0527ec4da84..503355d7dcc 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -14,4 +14,7 @@ HOMEPAGE = https://github.com/mozilla-services/syncstorage-rs/ COMMENT = Mozilla Sync Storage built with Rust. LICENSE = https://github.com/mozilla-services/syncstorage-rs/blob/master/LICENSE +# install the main server program +CARGO_BUILD_ARGS += --path ./syncserver --no-default-features --features=syncstorage-db/mysql --locked + include ../../mk/spksrc.cross-rust.mk From 4d86ff5a85cc059e8e0c7898d02a3ab83478fd7e Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Mon, 27 Nov 2023 20:57:38 -0400 Subject: [PATCH 07/54] Amend rust build args --- cross/syncstorage-rs/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 503355d7dcc..6fe253d582e 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -14,7 +14,8 @@ HOMEPAGE = https://github.com/mozilla-services/syncstorage-rs/ COMMENT = Mozilla Sync Storage built with Rust. LICENSE = https://github.com/mozilla-services/syncstorage-rs/blob/master/LICENSE -# install the main server program -CARGO_BUILD_ARGS += --path ./syncserver --no-default-features --features=syncstorage-db/mysql --locked +# arguments to install the main server program +RUST_SRC_DIR = $(WORK_DIR)/$(PKG_DIR)/syncserver +ENV += RUSTFLAGS="--no-default-features --features=syncstorage-db/mysql --locked" include ../../mk/spksrc.cross-rust.mk From 05adf10a66cfec1479d50c4a5ff8178a11f0d2f3 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Mon, 27 Nov 2023 22:28:37 -0400 Subject: [PATCH 08/54] Alternate fix for rust build args --- cross/syncstorage-rs/Makefile | 4 +++- mk/spksrc.cross-rust.mk | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 6fe253d582e..e896c989cac 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -16,6 +16,8 @@ LICENSE = https://github.com/mozilla-services/syncstorage-rs/blob/master/LICENS # arguments to install the main server program RUST_SRC_DIR = $(WORK_DIR)/$(PKG_DIR)/syncserver -ENV += RUSTFLAGS="--no-default-features --features=syncstorage-db/mysql --locked" +CARGO_BUILD_ARGS += --no-default-features +CARGO_BUILD_ARGS += --features=syncstorage-db/mysql +CARGO_BUILD_ARGS += --locked include ../../mk/spksrc.cross-rust.mk diff --git a/mk/spksrc.cross-rust.mk b/mk/spksrc.cross-rust.mk index e6385916b26..73c9e215885 100644 --- a/mk/spksrc.cross-rust.mk +++ b/mk/spksrc.cross-rust.mk @@ -53,10 +53,14 @@ endif CARGO_INSTALL_ARGS += --path $(RUST_SRC_DIR) CARGO_INSTALL_ARGS += --root $(STAGING_INSTALL_PREFIX) +ifeq ($(strip $(CARGO_BUILD_ARGS)),) +CARGO_BUILD_ARGS = +endif + # Default build with rust and install with cargo rust_install_target: @echo " ==> Cargo install rust package $(PKG_NAME) ($(shell rustc --version); $(RUST_TOOLCHAIN))" - @$(RUN) cargo +$(RUST_TOOLCHAIN) install $(CARGO_INSTALL_ARGS) + @$(RUN) cargo +$(RUST_TOOLCHAIN) install $(CARGO_INSTALL_ARGS) $(CARGO_BUILD_ARGS) ##### From 167cafb7ae3d938fea28cba1cd2a5adf468d3562 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Tue, 28 Nov 2023 00:44:02 -0400 Subject: [PATCH 09/54] Initial fixes from review --- spk/ffsync/Makefile | 11 +++++++++++ spk/ffsync/src/requirements.txt | 8 +++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index fc0024faf43..50b6773aec8 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -34,6 +34,17 @@ ADMIN_PORT = $(SERVICE_PORT) CONF_DIR = src/conf/ +# [mysqlclient] +DEPENDS += cross/mysql-connector-c cross/mariadb-connector-c +ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/include/mariadb -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" +ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" + +# [bcrypt] and [cryptography] +# Mandatory for rustc wheel building +ENV += PYO3_CROSS_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib/ +ENV += PYO3_CROSS_INCLUDE_DIR=$(STAGING_INSTALL_PREFIX)/include/ +ENV += CRYPTOGRAPHY_DONT_BUILD_RUST=1 + POST_STRIP_TARGET = ffsync_extra_install include ../../mk/spksrc.spk.mk diff --git a/spk/ffsync/src/requirements.txt b/spk/ffsync/src/requirements.txt index 1dce0f3374e..43658a8eecc 100644 --- a/spk/ffsync/src/requirements.txt +++ b/spk/ffsync/src/requirements.txt @@ -13,9 +13,15 @@ tokenlib==2.0.0 boto==2.49.0 hawkauthlib==2.0.0 -mysqlclient==2.1.1 pyramid==2.0.1 sqlalchemy==1.4.46 testfixtures tokenlib==2.0.0 PyBrowserID==0.14.0 + +# [mysqlclient] +# Depends: mysql-connector-c, mariadb-connector-c +# Require environment variables +# MYSQLCLIENT_CFLAGS +# MYSQLCLIENT_LDFLAGS +mysqlclient==2.1.1 From 988f41dc11687fd45a9059e5ed0caaa365afd8b3 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Tue, 28 Nov 2023 05:52:35 -0400 Subject: [PATCH 10/54] Split up wheels requirements --- spk/ffsync/Makefile | 2 +- ...{requirements.txt => requirements-all.txt} | 0 spk/ffsync/src/requirements-crossenv.txt | 19 +++++++++++++++++++ spk/ffsync/src/requirements-pure.txt | 14 ++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) rename spk/ffsync/src/{requirements.txt => requirements-all.txt} (100%) create mode 100644 spk/ffsync/src/requirements-crossenv.txt create mode 100644 spk/ffsync/src/requirements-pure.txt diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index 50b6773aec8..4a771703cb0 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -7,7 +7,7 @@ BUILD_DEPENDS = cross/curl cross/mysql-connector-c DEPENDS = cross/syncstorage-rs PYTHON_PACKAGE = python311 -WHEELS = src/requirements.txt +WHEELS = src/requirements-crossenv.txt src/requirements-pure.txt REQUIRED_MIN_DSM = 6.0 SPK_DEPENDS = MariaDB10:python311 diff --git a/spk/ffsync/src/requirements.txt b/spk/ffsync/src/requirements-all.txt similarity index 100% rename from spk/ffsync/src/requirements.txt rename to spk/ffsync/src/requirements-all.txt diff --git a/spk/ffsync/src/requirements-crossenv.txt b/spk/ffsync/src/requirements-crossenv.txt new file mode 100644 index 00000000000..7b4232ecd85 --- /dev/null +++ b/spk/ffsync/src/requirements-crossenv.txt @@ -0,0 +1,19 @@ +# From requirements.txt + +# We pin cryptography to 3.4.8 due to a build error that occurs with the +# current version (36.0.0 at the time of this commit). In short, building +# the cryptography package with Rust results in a segfault, so we need to +# set the CRYPTOGRAPHY_DONT_BUILD_RUST env var to force the package to build +# with C instead. This env var is only present in cryptography<3.5. +cryptography==3.4.8 + +# From tools/tokenserver/requirements.txt + +sqlalchemy==1.4.46 + +# [mysqlclient] +# Depends: mysql-connector-c, mariadb-connector-c +# Require environment variables +# MYSQLCLIENT_CFLAGS +# MYSQLCLIENT_LDFLAGS +mysqlclient==2.1.1 diff --git a/spk/ffsync/src/requirements-pure.txt b/spk/ffsync/src/requirements-pure.txt new file mode 100644 index 00000000000..307c2b9abe1 --- /dev/null +++ b/spk/ffsync/src/requirements-pure.txt @@ -0,0 +1,14 @@ +# From requirements.txt + +pyfxa==0.7.7 +tokenlib==2.0.0 + +# From tools/tokenserver/requirements.txt + +boto==2.49.0 +hawkauthlib==2.0.0 +pyramid==2.0.1 +sqlalchemy==1.4.46 +testfixtures +tokenlib==2.0.0 +PyBrowserID==0.14.0 From e6399740b87a9ccada91e0bd39a5b674c40bfedc Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Tue, 28 Nov 2023 07:28:11 -0400 Subject: [PATCH 11/54] Fix wheels requirements --- spk/ffsync/src/requirements-all.txt | 8 +------- spk/ffsync/src/requirements-crossenv.txt | 9 +++++++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/spk/ffsync/src/requirements-all.txt b/spk/ffsync/src/requirements-all.txt index 43658a8eecc..1dce0f3374e 100644 --- a/spk/ffsync/src/requirements-all.txt +++ b/spk/ffsync/src/requirements-all.txt @@ -13,15 +13,9 @@ tokenlib==2.0.0 boto==2.49.0 hawkauthlib==2.0.0 +mysqlclient==2.1.1 pyramid==2.0.1 sqlalchemy==1.4.46 testfixtures tokenlib==2.0.0 PyBrowserID==0.14.0 - -# [mysqlclient] -# Depends: mysql-connector-c, mariadb-connector-c -# Require environment variables -# MYSQLCLIENT_CFLAGS -# MYSQLCLIENT_LDFLAGS -mysqlclient==2.1.1 diff --git a/spk/ffsync/src/requirements-crossenv.txt b/spk/ffsync/src/requirements-crossenv.txt index 7b4232ecd85..de73d4d758d 100644 --- a/spk/ffsync/src/requirements-crossenv.txt +++ b/spk/ffsync/src/requirements-crossenv.txt @@ -5,15 +5,20 @@ # the cryptography package with Rust results in a segfault, so we need to # set the CRYPTOGRAPHY_DONT_BUILD_RUST env var to force the package to build # with C instead. This env var is only present in cryptography<3.5. + +# [bcrypt] & [cryptography] +# Require environment variables +# PYO3_CROSS_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib/ +# PYO3_CROSS_INCLUDE_DIR=$(STAGING_INSTALL_PREFIX)/include/ cryptography==3.4.8 # From tools/tokenserver/requirements.txt -sqlalchemy==1.4.46 - # [mysqlclient] # Depends: mysql-connector-c, mariadb-connector-c # Require environment variables # MYSQLCLIENT_CFLAGS # MYSQLCLIENT_LDFLAGS mysqlclient==2.1.1 + +sqlalchemy==1.4.46 From 3175be5774c09b6f66f0f8d5089c8480a85124ee Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Tue, 28 Nov 2023 08:02:07 -0400 Subject: [PATCH 12/54] Amend wheels requirements fix --- cross/syncstorage-rs/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index e896c989cac..5b4e55543bb 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -14,6 +14,10 @@ HOMEPAGE = https://github.com/mozilla-services/syncstorage-rs/ COMMENT = Mozilla Sync Storage built with Rust. LICENSE = https://github.com/mozilla-services/syncstorage-rs/blob/master/LICENSE +# Mandatory for rustc wheel building +ENV += PYO3_CROSS_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib/ +ENV += PYO3_CROSS_INCLUDE_DIR=$(STAGING_INSTALL_PREFIX)/include/ + # arguments to install the main server program RUST_SRC_DIR = $(WORK_DIR)/$(PKG_DIR)/syncserver CARGO_BUILD_ARGS += --no-default-features From 0a6ff26f61edabb51e5108c832a03f600c45ea5a Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Wed, 29 Nov 2023 08:43:28 -0400 Subject: [PATCH 13/54] Framework: Add rust build args --- mk/spksrc.cross-rust.mk | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mk/spksrc.cross-rust.mk b/mk/spksrc.cross-rust.mk index 73c9e215885..af03e152713 100644 --- a/mk/spksrc.cross-rust.mk +++ b/mk/spksrc.cross-rust.mk @@ -53,14 +53,15 @@ endif CARGO_INSTALL_ARGS += --path $(RUST_SRC_DIR) CARGO_INSTALL_ARGS += --root $(STAGING_INSTALL_PREFIX) -ifeq ($(strip $(CARGO_BUILD_ARGS)),) -CARGO_BUILD_ARGS = +# Append additional install options if present +ifneq ($(strip $(CARGO_BUILD_ARGS)),) +CARGO_INSTALL_ARGS += $(CARGO_BUILD_ARGS) endif # Default build with rust and install with cargo rust_install_target: @echo " ==> Cargo install rust package $(PKG_NAME) ($(shell rustc --version); $(RUST_TOOLCHAIN))" - @$(RUN) cargo +$(RUST_TOOLCHAIN) install $(CARGO_INSTALL_ARGS) $(CARGO_BUILD_ARGS) + @$(RUN) cargo +$(RUST_TOOLCHAIN) install $(CARGO_INSTALL_ARGS) ##### From 1cd002676172017e4cd13b695662b087a5fa1496 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Wed, 29 Nov 2023 21:58:04 -0400 Subject: [PATCH 14/54] Optimise python build --- spk/ffsync/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index 4a771703cb0..f371a34cb79 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -10,7 +10,7 @@ PYTHON_PACKAGE = python311 WHEELS = src/requirements-crossenv.txt src/requirements-pure.txt REQUIRED_MIN_DSM = 6.0 -SPK_DEPENDS = MariaDB10:python311 +SPK_DEPENDS = MariaDB10:$(PYTHON_PACKAGE) MAINTAINER = SynoCommunity DESCRIPTION = Firefox Sync Server 1.5, used for Firefox 29 and later. You can use Firefox Sync Server to synchronize your bookmarks, passwords, settings, history, add-ons and tabs with Firefox on other computers. The service runs on port 8132. @@ -47,7 +47,7 @@ ENV += CRYPTOGRAPHY_DONT_BUILD_RUST=1 POST_STRIP_TARGET = ffsync_extra_install -include ../../mk/spksrc.spk.mk +include ../../mk/spksrc.python.mk .PHONY: ffsync_extra_install ffsync_extra_install: From d09298872013b4bbb904a0807d72563b773740c7 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Wed, 29 Nov 2023 22:44:49 -0400 Subject: [PATCH 15/54] Testing build without rustc wheel directive --- spk/ffsync/Makefile | 6 ------ 1 file changed, 6 deletions(-) diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index f371a34cb79..d84d0efb0b6 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -39,12 +39,6 @@ DEPENDS += cross/mysql-connector-c cross/mariadb-connector-c ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/include/mariadb -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" -# [bcrypt] and [cryptography] -# Mandatory for rustc wheel building -ENV += PYO3_CROSS_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib/ -ENV += PYO3_CROSS_INCLUDE_DIR=$(STAGING_INSTALL_PREFIX)/include/ -ENV += CRYPTOGRAPHY_DONT_BUILD_RUST=1 - POST_STRIP_TARGET = ffsync_extra_install include ../../mk/spksrc.python.mk From e8aab6b5aca4c2e320e2159bf953486a478545aa Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:30:50 -0400 Subject: [PATCH 16/54] Version bump and fixes for build Co-Authored-By: hgy59 <12009964+hgy59@users.noreply.github.com> --- cross/syncstorage-rs/Makefile | 5 +++-- cross/syncstorage-rs/PLIST | 1 + cross/syncstorage-rs/digests | 6 +++--- .../patches/01-tokenserver-auth_pyo3-version.patch | 11 +++++++++++ spk/ffsync/Makefile | 7 +------ spk/ffsync/src/{ => TO_REMOVE}/requirements-all.txt | 0 6 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 cross/syncstorage-rs/PLIST create mode 100644 cross/syncstorage-rs/patches/01-tokenserver-auth_pyo3-version.patch rename spk/ffsync/src/{ => TO_REMOVE}/requirements-all.txt (100%) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 5b4e55543bb..c81b4207728 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -1,11 +1,12 @@ PKG_NAME = syncstorage-rs -PKG_VERS = 0.14.1 +PKG_VERS = 0.14.3 PKG_EXT = tar.gz PKG_DIST_NAME = $(PKG_NAME)-$(PKG_VERS).$(PKG_EXT) PKG_DIST_SITE = https://github.com/mozilla-services/$(PKG_NAME)/archive/${PKG_VERS} PKG_DIR = $(PKG_NAME)-$(PKG_VERS) -DEPENDS = +BUILD_DEPENDS = cross/python311 +DEPENDS += cross/openssl3 cross/mysql-connector-c # powerpc archs (except qoriq) are not supported UNSUPPORTED_ARCHS += $(OLD_PPC_ARCHS) diff --git a/cross/syncstorage-rs/PLIST b/cross/syncstorage-rs/PLIST new file mode 100644 index 00000000000..1a9c2bf8073 --- /dev/null +++ b/cross/syncstorage-rs/PLIST @@ -0,0 +1 @@ +bin:bin/syncserver diff --git a/cross/syncstorage-rs/digests b/cross/syncstorage-rs/digests index 4be5997e9b8..e0f50a12217 100644 --- a/cross/syncstorage-rs/digests +++ b/cross/syncstorage-rs/digests @@ -1,3 +1,3 @@ -syncstorage-rs-0.14.1.tar.gz SHA1 2b4fd69655caf646bed046fcc85db4ef844f0746 -syncstorage-rs-0.14.1.tar.gz SHA256 224d8c4af114b0af4eebd90decef951a08dde1204c13caada416347aa5ebe35c -syncstorage-rs-0.14.1.tar.gz MD5 de9034fc2fcc5bcbccf9df5c0e86f405 +syncstorage-rs-0.14.3.tar.gz SHA1 0982c8f6d471d277b94596ecca6d8966e26826f4 +syncstorage-rs-0.14.3.tar.gz SHA256 7ece5b08b2160b04ff01fa1fa61069973a63ec2f6aa34ae53fc29c9252539d96 +syncstorage-rs-0.14.3.tar.gz MD5 8b96d242d3e194b50c4f2ffa18b8979f diff --git a/cross/syncstorage-rs/patches/01-tokenserver-auth_pyo3-version.patch b/cross/syncstorage-rs/patches/01-tokenserver-auth_pyo3-version.patch new file mode 100644 index 00000000000..bcd80dbfebe --- /dev/null +++ b/cross/syncstorage-rs/patches/01-tokenserver-auth_pyo3-version.patch @@ -0,0 +1,11 @@ +--- tokenserver-auth/Cargo.toml.orig 2023-11-30 02:34:56.000000000 +0000 ++++ tokenserver-auth/Cargo.toml 2023-11-30 18:24:35.953670206 +0000 +@@ -14,7 +14,7 @@ + + async-trait = "0.1.40" + dyn-clone = "1.0.4" +-pyo3 = { version = "0.14", features = ["auto-initialize"] } ++pyo3 = { version = "0.17", features = ["auto-initialize"] } + reqwest = { version = "0.10.10", features = ["json", "rustls-tls"] } + syncserver-common = { path = "../syncserver-common" } + tokenserver-common = { path = "../tokenserver-common" } diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index d84d0efb0b6..f28179aa1fd 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -1,5 +1,5 @@ SPK_NAME = ffsync -SPK_VERS = 0.14.1 +SPK_VERS = 0.14.3 SPK_REV = 4 SPK_ICON = src/ffsync.png @@ -34,11 +34,6 @@ ADMIN_PORT = $(SERVICE_PORT) CONF_DIR = src/conf/ -# [mysqlclient] -DEPENDS += cross/mysql-connector-c cross/mariadb-connector-c -ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/include/mariadb -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" -ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" - POST_STRIP_TARGET = ffsync_extra_install include ../../mk/spksrc.python.mk diff --git a/spk/ffsync/src/requirements-all.txt b/spk/ffsync/src/TO_REMOVE/requirements-all.txt similarity index 100% rename from spk/ffsync/src/requirements-all.txt rename to spk/ffsync/src/TO_REMOVE/requirements-all.txt From dbe9e55f26e10b28b1f93e842ffaea3bddbeb536 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:13:15 -0400 Subject: [PATCH 17/54] Additional fixes for build --- cross/syncstorage-rs/Makefile | 3 --- spk/ffsync/Makefile | 9 +++++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index c81b4207728..320f66c53a7 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -5,9 +5,6 @@ PKG_DIST_NAME = $(PKG_NAME)-$(PKG_VERS).$(PKG_EXT) PKG_DIST_SITE = https://github.com/mozilla-services/$(PKG_NAME)/archive/${PKG_VERS} PKG_DIR = $(PKG_NAME)-$(PKG_VERS) -BUILD_DEPENDS = cross/python311 -DEPENDS += cross/openssl3 cross/mysql-connector-c - # powerpc archs (except qoriq) are not supported UNSUPPORTED_ARCHS += $(OLD_PPC_ARCHS) diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index f28179aa1fd..56566d0afe5 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -9,6 +9,8 @@ DEPENDS = cross/syncstorage-rs PYTHON_PACKAGE = python311 WHEELS = src/requirements-crossenv.txt src/requirements-pure.txt +UNSUPPORTED_ARCHS = $(ARMv5_ARCHS) + REQUIRED_MIN_DSM = 6.0 SPK_DEPENDS = MariaDB10:$(PYTHON_PACKAGE) @@ -34,11 +36,14 @@ ADMIN_PORT = $(SERVICE_PORT) CONF_DIR = src/conf/ +# [mysqlclient] +DEPENDS += cross/mysql-connector-c cross/mariadb-connector-c +ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/include/mariadb -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" +ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" + POST_STRIP_TARGET = ffsync_extra_install include ../../mk/spksrc.python.mk .PHONY: ffsync_extra_install ffsync_extra_install: - install -m 755 -d $(STAGING_DIR)/var - install -m 644 src/ffsync.ini $(STAGING_DIR)/var/ From 5ae59a9c19f71cd9b386ea7ab3cdce76d75f235c Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Thu, 30 Nov 2023 22:54:11 -0400 Subject: [PATCH 18/54] Fixes for scripts and build --- cross/syncstorage-rs/Makefile | 4 ++++ spk/ffsync/Makefile | 7 ++----- spk/ffsync/src/service-setup.sh | 33 +++++++++++---------------------- spk/ffsync/src/var/local.toml | 22 ++++++++++++++++++++++ 4 files changed, 39 insertions(+), 27 deletions(-) create mode 100644 spk/ffsync/src/var/local.toml diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 320f66c53a7..e2e0ad7d336 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -22,4 +22,8 @@ CARGO_BUILD_ARGS += --no-default-features CARGO_BUILD_ARGS += --features=syncstorage-db/mysql CARGO_BUILD_ARGS += --locked +# [mysqlclient] +ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" +ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" + include ../../mk/spksrc.cross-rust.mk diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index 56566d0afe5..e036b824d28 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -36,14 +36,11 @@ ADMIN_PORT = $(SERVICE_PORT) CONF_DIR = src/conf/ -# [mysqlclient] -DEPENDS += cross/mysql-connector-c cross/mariadb-connector-c -ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/include/mariadb -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" -ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" - POST_STRIP_TARGET = ffsync_extra_install include ../../mk/spksrc.python.mk .PHONY: ffsync_extra_install ffsync_extra_install: + install -m 755 -d $(STAGING_DIR)/var + install -m 644 src/var/local.toml $(STAGING_DIR)/var/ diff --git a/spk/ffsync/src/service-setup.sh b/spk/ffsync/src/service-setup.sh index 6391277842d..b9a63df05c3 100644 --- a/spk/ffsync/src/service-setup.sh +++ b/spk/ffsync/src/service-setup.sh @@ -11,7 +11,7 @@ CFG_FILE="${HOME}/config/local.toml" SERVICE_COMMAND="${SYNCSERVER} --config=${CFG_FILE}" -service_preinst () +validate_preinst () { # Check MySQL database if [ "${SYNOPKG_PKG_STATUS}" = "INSTALL" ]; then @@ -75,29 +75,18 @@ EOF # Setup syncserver config file MASTER_SECRET="$(cat /dev/urandom | base32 | head -c64)" METRICS_HASH_SECRET="$(cat /dev/urandom | base32 | head -c64)" - cat > ${CFG_FILE} < Date: Fri, 1 Dec 2023 08:16:36 -0400 Subject: [PATCH 19/54] Add password validation to wizards --- spk/ffsync/src/wizard/install_uifile | 28 -------- spk/ffsync/src/wizard/install_uifile.sh | 81 +++++++++++++++++++++++ spk/ffsync/src/wizard/uninstall_uifile | 27 -------- spk/ffsync/src/wizard/uninstall_uifile.sh | 73 ++++++++++++++++++++ 4 files changed, 154 insertions(+), 55 deletions(-) delete mode 100644 spk/ffsync/src/wizard/install_uifile create mode 100644 spk/ffsync/src/wizard/install_uifile.sh delete mode 100644 spk/ffsync/src/wizard/uninstall_uifile create mode 100644 spk/ffsync/src/wizard/uninstall_uifile.sh diff --git a/spk/ffsync/src/wizard/install_uifile b/spk/ffsync/src/wizard/install_uifile deleted file mode 100644 index 795f4a0e49e..00000000000 --- a/spk/ffsync/src/wizard/install_uifile +++ /dev/null @@ -1,28 +0,0 @@ -[{ - "step_title": "Firefox Sync Server 1.5 database configuration", - "items": [{ - "type": "password", - "desc": "Enter your MySQL root password", - "subitems": [{ - "key": "wizard_mysql_password_root", - "desc": "Root password" - }] - }, { - "type": "password", - "desc": "A 'ffsync' user and database will be created. Please enter a password for the 'ffsync' user.", - "subitems": [{ - "key": "wizard_password_ffsync", - "desc": "ffsync password" - }] - }] -}, { - "step_title": "Public URL", - "items": [{ - "type": "textfield", - "desc": "Provide the client-visible URL. The URL to configure on your device is:

http://public-url:8132/token/1.0/sync/1.5

Note: Configure a reverse proxy for SSL support", - "subitems": [{ - "key": "wizard_ffsync_public_url", - "desc": "Public URL" - }] - }] -}] diff --git a/spk/ffsync/src/wizard/install_uifile.sh b/spk/ffsync/src/wizard/install_uifile.sh new file mode 100644 index 00000000000..61df9db8098 --- /dev/null +++ b/spk/ffsync/src/wizard/install_uifile.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +quote_json () +{ + sed -e 's|\\|\\\\|g' -e 's|\"|\\\"|g' +} + +page_append () +{ + if [ -z "$1" ]; then + echo "$2" + elif [ -z "$2" ]; then + echo "$1" + else + echo "$1,$2" + fi +} + +getPasswordValidator() +{ + validator=$(/bin/cat<
http://public-url:8132/token/1.0/sync/1.5

Note: Configure a reverse proxy for SSL support", + "subitems": [{ + "key": "wizard_ffsync_public_url", + "desc": "Public URL", + "validator": { + "allowBlank": false + } + }] + }] +} +EOF +) + +main () { + local install_page="" + install_page=$(page_append "$install_page" "$PAGE_FFSYNC_SETUP") + echo "[$install_page]" > "${SYNOPKG_TEMP_LOGFILE}" +} + +main "$@" diff --git a/spk/ffsync/src/wizard/uninstall_uifile b/spk/ffsync/src/wizard/uninstall_uifile deleted file mode 100644 index 66be36095d2..00000000000 --- a/spk/ffsync/src/wizard/uninstall_uifile +++ /dev/null @@ -1,27 +0,0 @@ -[{ - "step_title": "Remove Firefox Sync Server 1.5 database", - "items": [{ - "desc": "Attention: The Firefox Sync Server 1.5 database will be removed during package uninstallation. All users and sync data will be deleted." - }, { - "type": "password", - "desc": "Enter your MySQL password", - "subitems": [{ - "key": "wizard_mysql_password_root", - "desc": "Root password" - }] - }, { - "type": "textfield", - "desc": "Optional: Provide directory for database export. Leave blank to skip export. The directory will be created if it does not exist", - "subitems": [{ - "key": "wizard_dbexport_path", - "desc": "Database export location", - "validator": { - "allowBlank": true, - "regex": { - "expr": "/^\\\/volume[0-9]+\\\//", - "errorText": "Path should begin with /volume?/ with ? the number of the volume" - } - } - }] - }] -}] diff --git a/spk/ffsync/src/wizard/uninstall_uifile.sh b/spk/ffsync/src/wizard/uninstall_uifile.sh new file mode 100644 index 00000000000..f09695e6922 --- /dev/null +++ b/spk/ffsync/src/wizard/uninstall_uifile.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +quote_json () +{ + sed -e 's|\\|\\\\|g' -e 's|\"|\\\"|g' +} + +page_append () +{ + if [ -z "$1" ]; then + echo "$2" + elif [ -z "$2" ]; then + echo "$1" + else + echo "$1,$2" + fi +} + +getPasswordValidator() +{ + validator=$(/bin/cat< "${SYNOPKG_TEMP_LOGFILE}" +} + +main "$@" From 18bf9f6f8ceff1115b8fa255be644c9e94b46ee0 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Fri, 1 Dec 2023 08:48:32 -0400 Subject: [PATCH 20/54] Testing build with self-contained dependencies --- cross/syncstorage-rs/Makefile | 7 ++++++- spk/ffsync/Makefile | 1 - 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index e2e0ad7d336..802b39326b8 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -22,7 +22,12 @@ CARGO_BUILD_ARGS += --no-default-features CARGO_BUILD_ARGS += --features=syncstorage-db/mysql CARGO_BUILD_ARGS += --locked -# [mysqlclient] +# only required for build in cross/syncstorage-rs folder (not when using prebuilt spk/python311) +#BUILD_DEPENDS = cross/python311 +# for openssl-sys +DEPENDS = cross/openssl3 +# for mysqlclient +DEPENDS += cross/mysql-connector-c ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index e036b824d28..80600d110ab 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -3,7 +3,6 @@ SPK_VERS = 0.14.3 SPK_REV = 4 SPK_ICON = src/ffsync.png -BUILD_DEPENDS = cross/curl cross/mysql-connector-c DEPENDS = cross/syncstorage-rs PYTHON_PACKAGE = python311 From 9d9b038c66e543ee2458a04e322f991e82ccc372 Mon Sep 17 00:00:00 2001 From: hgy59 Date: Fri, 1 Dec 2023 16:41:07 +0100 Subject: [PATCH 21/54] Update cross/syncstorage-rs/Makefile --- cross/syncstorage-rs/Makefile | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 802b39326b8..4daa1db10c1 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -28,7 +28,16 @@ CARGO_BUILD_ARGS += --locked DEPENDS = cross/openssl3 # for mysqlclient DEPENDS += cross/mysql-connector-c -ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" -ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" + +# To find libpython in prebuilt or local built python +ifneq ($(PYTHON_STAGING_PREFIX),) +# use prebuilt python +ENV += PYO3_CROSS_LIB_DIR=$(PYTHON_STAGING_PREFIX)/lib/ +ENV += PYO3_CROSS_INCLUDE_DIR=$(PYTHON_STAGING_PREFIX)/include/ +else +# use local python (together with "BUILD_DEPENDS = cross/python311" above) +ENV += PYO3_CROSS_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib/ +ENV += PYO3_CROSS_INCLUDE_DIR=$(STAGING_INSTALL_PREFIX)/include/ +endif include ../../mk/spksrc.cross-rust.mk From 8f1e5770842423ef85bd8f94922a90da092f4fec Mon Sep 17 00:00:00 2001 From: Michael Reid Date: Fri, 1 Dec 2023 12:05:22 -0400 Subject: [PATCH 22/54] Remove duplicate ENV assignment --- cross/syncstorage-rs/Makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 4daa1db10c1..4567c296126 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -12,10 +12,6 @@ HOMEPAGE = https://github.com/mozilla-services/syncstorage-rs/ COMMENT = Mozilla Sync Storage built with Rust. LICENSE = https://github.com/mozilla-services/syncstorage-rs/blob/master/LICENSE -# Mandatory for rustc wheel building -ENV += PYO3_CROSS_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib/ -ENV += PYO3_CROSS_INCLUDE_DIR=$(STAGING_INSTALL_PREFIX)/include/ - # arguments to install the main server program RUST_SRC_DIR = $(WORK_DIR)/$(PKG_DIR)/syncserver CARGO_BUILD_ARGS += --no-default-features From baecf94991157aec97dc99b384b46ef761e0ef04 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Fri, 1 Dec 2023 13:03:23 -0400 Subject: [PATCH 23/54] Fix for mysqlclient dependencies --- cross/syncstorage-rs/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 4567c296126..234d6e519c4 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -24,6 +24,8 @@ CARGO_BUILD_ARGS += --locked DEPENDS = cross/openssl3 # for mysqlclient DEPENDS += cross/mysql-connector-c +ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" +ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" # To find libpython in prebuilt or local built python ifneq ($(PYTHON_STAGING_PREFIX),) From 0926673826f850b82a0d808325699653e7e9cef1 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Fri, 1 Dec 2023 13:45:44 -0400 Subject: [PATCH 24/54] Amend fix for mysqlclient dependencies --- cross/syncstorage-rs/Makefile | 2 -- spk/ffsync/Makefile | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 234d6e519c4..4567c296126 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -24,8 +24,6 @@ CARGO_BUILD_ARGS += --locked DEPENDS = cross/openssl3 # for mysqlclient DEPENDS += cross/mysql-connector-c -ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" -ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" # To find libpython in prebuilt or local built python ifneq ($(PYTHON_STAGING_PREFIX),) diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index 80600d110ab..206666f96eb 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -35,6 +35,10 @@ ADMIN_PORT = $(SERVICE_PORT) CONF_DIR = src/conf/ +# [mysqlclient] +ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" +ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" + POST_STRIP_TARGET = ffsync_extra_install include ../../mk/spksrc.python.mk From dbe934c3eb2a22076639ba23ca4c672c9b786789 Mon Sep 17 00:00:00 2001 From: hgy59 Date: Fri, 1 Dec 2023 21:54:58 +0100 Subject: [PATCH 25/54] add cross/diesel --- cross/diesel/Makefile | 28 ++++++++++++++++++++++++++++ cross/diesel/PLIST | 1 + cross/diesel/digests | 3 +++ 3 files changed, 32 insertions(+) create mode 100644 cross/diesel/Makefile create mode 100644 cross/diesel/PLIST create mode 100644 cross/diesel/digests diff --git a/cross/diesel/Makefile b/cross/diesel/Makefile new file mode 100644 index 00000000000..9e7abb0b8ca --- /dev/null +++ b/cross/diesel/Makefile @@ -0,0 +1,28 @@ +PKG_NAME = diesel +PKG_VERS = 2.1.4 +PKG_EXT = tar.gz +PKG_DIST_NAME = v$(PKG_VERS).$(PKG_EXT) +PKG_DIST_SITE = https://github.com/diesel-rs/diesel/archive +PKG_DIST_FILE = $(PKG_NAME)-$(PKG_VERS).$(PKG_EXT) +PKG_DIR = $(PKG_NAME)-$(PKG_VERS) + +DEPENDS += cross/mysql-connector-c + +# powerpc archs (except qoriq) are not supported +UNSUPPORTED_ARCHS += $(OLD_PPC_ARCHS) + +HOMEPAGE = https://diesel.rs/ +COMMENT = A safe, extensible ORM and Query Builder for Rust. +LICENSE = MIT + +# build the cli tool for mysql +RUST_SRC_DIR = $(WORK_DIR)/$(PKG_DIR)/diesel_cli +CARGO_BUILD_ARGS += --no-default-features +CARGO_BUILD_ARGS += --features=mysql + +# mysqlclient-sys: to find libmysqlclient +ENV += MYSQLCLIENT_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib +# to find dependencies of libmysqlclient (libz) +ENV += RUSTFLAGS="-Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib -Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib" + +include ../../mk/spksrc.cross-rust.mk diff --git a/cross/diesel/PLIST b/cross/diesel/PLIST new file mode 100644 index 00000000000..c2b783bb865 --- /dev/null +++ b/cross/diesel/PLIST @@ -0,0 +1 @@ +bin:bin/diesel diff --git a/cross/diesel/digests b/cross/diesel/digests new file mode 100644 index 00000000000..bc4d98c7631 --- /dev/null +++ b/cross/diesel/digests @@ -0,0 +1,3 @@ +diesel-2.1.4.tar.gz SHA1 ea4fd4a77bcd90038a04bcfefcee7448b63e5b03 +diesel-2.1.4.tar.gz SHA256 5aac923078a5b431902d75cfca36f2990b3f11dbb2bbbc44f4538305af939657 +diesel-2.1.4.tar.gz MD5 d570cfe9013331fad318a94a6a389b8d From a4af41dba552dc3eeaa78b8b376f7f6f7f2c9c5c Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Fri, 1 Dec 2023 17:15:28 -0400 Subject: [PATCH 26/54] Minor fixes --- spk/ffsync/src/service-setup.sh | 4 ++-- spk/ffsync/src/wizard/install_uifile.sh | 22 +++++++++++++++++----- spk/ffsync/src/wizard/uninstall_uifile.sh | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/spk/ffsync/src/service-setup.sh b/spk/ffsync/src/service-setup.sh index b9a63df05c3..7653d375dbc 100644 --- a/spk/ffsync/src/service-setup.sh +++ b/spk/ffsync/src/service-setup.sh @@ -43,7 +43,7 @@ service_postinst () if [ "${SYNOPKG_PKG_STATUS}" = "INSTALL" ]; then # login as root sql user using whatever creds you set up for that # this sets up a user for sync storage and sets up the databases - ${MYSQL} -u root -p ${wizard_mysql_password_root} < Date: Fri, 1 Dec 2023 22:23:35 +0100 Subject: [PATCH 27/54] cross/syncstorage-rs: fix build linker flags --- cross/syncstorage-rs/Makefile | 21 ++++++++++++------- .../01-tokenserver-auth_pyo3-version.patch | 6 ++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 4567c296126..29d26f55432 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -5,12 +5,19 @@ PKG_DIST_NAME = $(PKG_NAME)-$(PKG_VERS).$(PKG_EXT) PKG_DIST_SITE = https://github.com/mozilla-services/$(PKG_NAME)/archive/${PKG_VERS} PKG_DIR = $(PKG_NAME)-$(PKG_VERS) +# only required for build in cross/syncstorage-rs folder (not when using prebuilt spk/python311) +#BUILD_DEPENDS = cross/python311 +# for openssl-sys +DEPENDS = cross/openssl3 +# for mysqlclient-sys +DEPENDS += cross/mysql-connector-c + # powerpc archs (except qoriq) are not supported UNSUPPORTED_ARCHS += $(OLD_PPC_ARCHS) HOMEPAGE = https://github.com/mozilla-services/syncstorage-rs/ COMMENT = Mozilla Sync Storage built with Rust. -LICENSE = https://github.com/mozilla-services/syncstorage-rs/blob/master/LICENSE +LICENSE = MPL 2.0 # arguments to install the main server program RUST_SRC_DIR = $(WORK_DIR)/$(PKG_DIR)/syncserver @@ -18,13 +25,6 @@ CARGO_BUILD_ARGS += --no-default-features CARGO_BUILD_ARGS += --features=syncstorage-db/mysql CARGO_BUILD_ARGS += --locked -# only required for build in cross/syncstorage-rs folder (not when using prebuilt spk/python311) -#BUILD_DEPENDS = cross/python311 -# for openssl-sys -DEPENDS = cross/openssl3 -# for mysqlclient -DEPENDS += cross/mysql-connector-c - # To find libpython in prebuilt or local built python ifneq ($(PYTHON_STAGING_PREFIX),) # use prebuilt python @@ -36,4 +36,9 @@ ENV += PYO3_CROSS_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib/ ENV += PYO3_CROSS_INCLUDE_DIR=$(STAGING_INSTALL_PREFIX)/include/ endif +# mysqlclient-sys: to find libmysqlclient +ENV += MYSQLCLIENT_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib +# to find dependencies of libmysqlclient (libz) +ENV += RUSTFLAGS="-Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib -Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib" + include ../../mk/spksrc.cross-rust.mk diff --git a/cross/syncstorage-rs/patches/01-tokenserver-auth_pyo3-version.patch b/cross/syncstorage-rs/patches/01-tokenserver-auth_pyo3-version.patch index bcd80dbfebe..f9bcdf7ef7f 100644 --- a/cross/syncstorage-rs/patches/01-tokenserver-auth_pyo3-version.patch +++ b/cross/syncstorage-rs/patches/01-tokenserver-auth_pyo3-version.patch @@ -1,3 +1,9 @@ +# pyo3 0.14.2 (as locked in Cargo.lock) does not support Python 3.10 and 3.11 +# error: the configured Python interpreter version (3.1) is lower than PyO3's minimum supported version (3.6) +# +# This patch updates to pyo3 0.17.* +# At time of writing pyo3 0.17.3 is used +# --- tokenserver-auth/Cargo.toml.orig 2023-11-30 02:34:56.000000000 +0000 +++ tokenserver-auth/Cargo.toml 2023-11-30 18:24:35.953670206 +0000 @@ -14,7 +14,7 @@ From d3181456855607b79655863490ac0a2ed7a23b80 Mon Sep 17 00:00:00 2001 From: hgy59 Date: Fri, 1 Dec 2023 22:25:59 +0100 Subject: [PATCH 28/54] spk/ffsync: fix cross build of cryptography and library path - disable rust for old cryptography wheel - patch runtime library path into binaries built with rust - add diesel --- spk/ffsync/Makefile | 30 ++++++++++++++++++++---------- spk/ffsync/src/conf/privilege | 31 ------------------------------- 2 files changed, 20 insertions(+), 41 deletions(-) delete mode 100644 spk/ffsync/src/conf/privilege diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index 206666f96eb..87fae804026 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -3,24 +3,23 @@ SPK_VERS = 0.14.3 SPK_REV = 4 SPK_ICON = src/ffsync.png -DEPENDS = cross/syncstorage-rs +DEPENDS = cross/syncstorage-rs cross/diesel PYTHON_PACKAGE = python311 -WHEELS = src/requirements-crossenv.txt src/requirements-pure.txt +WHEELS = src/requirements-crossenv.txt src/requirements-pure.txt -UNSUPPORTED_ARCHS = $(ARMv5_ARCHS) +UNSUPPORTED_ARCHS = $(ARMv5_ARCHS) $(OLD_PPC_ARCHS) REQUIRED_MIN_DSM = 6.0 SPK_DEPENDS = MariaDB10:$(PYTHON_PACKAGE) -MAINTAINER = SynoCommunity +MAINTAINER = SynoCommunity DESCRIPTION = Firefox Sync Server 1.5, used for Firefox 29 and later. You can use Firefox Sync Server to synchronize your bookmarks, passwords, settings, history, add-ons and tabs with Firefox on other computers. The service runs on port 8132. DISPLAY_NAME = Firefox Sync Server 1.5 CHANGELOG = "1. Upgrade to Mozilla Sync Storage built with Rust." -HOMEPAGE = https://mozilla-services.readthedocs.io/en/latest/howtos/run-sync-1.5.html -LICENSE = MPL-2.0 -HELPURL = https://github.com/SynoCommunity/spksrc/wiki/Firefox-Sync-Server-1.5 +HOMEPAGE = https://mozilla-services.readthedocs.io/en/latest/howtos/run-sync-1.5.html +LICENSE = MPL 2.0 WIZARDS_DIR = src/wizard/ @@ -33,7 +32,14 @@ SERVICE_PORT_TITLE = $(DISPLAY_NAME) # Admin link for in DSM UI ADMIN_PORT = $(SERVICE_PORT) -CONF_DIR = src/conf/ +# [cryptography] +# We pin cryptography to 3.4.8 due to a build error that occurs with the +# current version (36.0.0 at the time of this commit). In short, building +# the cryptography package with Rust results in a segfault, so we need to +# set the CRYPTOGRAPHY_DONT_BUILD_RUST env var to force the package to build +# with C instead. This env var is only present in cryptography<3.5. +ENV += CRYPTOGRAPHY_DONT_BUILD_RUST=1 + # [mysqlclient] ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" @@ -45,5 +51,9 @@ include ../../mk/spksrc.python.mk .PHONY: ffsync_extra_install ffsync_extra_install: - install -m 755 -d $(STAGING_DIR)/var - install -m 644 src/var/local.toml $(STAGING_DIR)/var/ + @$(MSG) Install config file + @install -m 755 -d $(STAGING_DIR)/var + @install -m 644 src/var/local.toml $(STAGING_DIR)/var/ + @$(MSG) Patch binaries built with rust to find shared libraries + @patchelf --set-rpath /var/packages/$(SPK_NAME)/target/lib:/var/packages/$(PYTHON_PACKAGE)/target/lib $(STAGING_DIR)/bin/syncserver + @patchelf --set-rpath /var/packages/$(SPK_NAME)/target/lib $(STAGING_DIR)/bin/diesel diff --git a/spk/ffsync/src/conf/privilege b/spk/ffsync/src/conf/privilege deleted file mode 100644 index 8b3e5509769..00000000000 --- a/spk/ffsync/src/conf/privilege +++ /dev/null @@ -1,31 +0,0 @@ -{ - "defaults":{ - "run-as": "package" - }, - "username": "sc-ffsync", - "ctrl-script": [{ - "action": "preinst", - "run-as": "root" - }, { - "action": "postinst", - "run-as": "root" - }, { - "action": "preuninst", - "run-as": "root" - }, { - "action": "postuninst", - "run-as": "root" - }, { - "action": "preupgrade", - "run-as": "root" - }, { - "action": "postupgrade", - "run-as": "root" - }, { - "action": "start", - "run-as": "root" - }, { - "action": "stop", - "run-as": "root" - }] -} \ No newline at end of file From 4e8141c3580f1f6a98ddb0ed4f60bda4d6a4fefd Mon Sep 17 00:00:00 2001 From: hgy59 Date: Fri, 1 Dec 2023 22:28:15 +0100 Subject: [PATCH 29/54] ffsync: improve package installation - define DBUSER for package db user (SPK_NAME is not defined) - use installed diesel binary - fix config file location - use a single sed call to patch config file --- spk/ffsync/src/service-setup.sh | 45 +++++++++++++++++---------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/spk/ffsync/src/service-setup.sh b/spk/ffsync/src/service-setup.sh index b9a63df05c3..83d6df6813d 100644 --- a/spk/ffsync/src/service-setup.sh +++ b/spk/ffsync/src/service-setup.sh @@ -1,16 +1,19 @@ PYTHON_DIR="/var/packages/python311/target/bin" PATH="${SYNOPKG_PKGDEST}/env/bin:${SYNOPKG_PKGDEST}/bin:${PYTHON_DIR}:${PATH}" + MARIADB_10_INSTALL_DIRECTORY="/var/packages/MariaDB10" MARIADB_10_BIN_DIRECTORY="${MARIADB_10_INSTALL_DIRECTORY}/target/usr/local/mariadb10/bin" MYSQL="${MARIADB_10_BIN_DIRECTORY}/mysql" PYTHON="${SYNOPKG_PKGDEST}/env/bin/python3" -SYNCSERVER="${HOME}/bin/syncserver" -HOME="${SYNOPKG_PKGDEST}/share/${SPK_NAME}" -CFG_FILE="${HOME}/config/local.toml" +SYNCSERVER="${SYNOPKG_PKGDEST}/bin/syncserver" +DIESEL="${SYNOPKG_PKGDEST}/bin/diesel" +CFG_FILE="${SYNOPKG_PKGVAR}/local.toml" SERVICE_COMMAND="${SYNCSERVER} --config=${CFG_FILE}" +DBUSER=ffsync + validate_preinst () { # Check MySQL database @@ -20,15 +23,15 @@ validate_preinst () echo "Incorrect MySQL root password" exit 1 fi - if ${MYSQL} -u root -p"${wizard_mysql_password_root}" mysql -e "SELECT User FROM user" | grep ^${SPK_NAME}$ > /dev/null 2>&1; then - echo "MySQL user ${SPK_NAME} already exists" + if ${MYSQL} -u root -p"${wizard_mysql_password_root}" mysql -e "SELECT User FROM user" | grep ^${DBUSER}$ > /dev/null 2>&1; then + echo "MySQL user ${DBUSER} already exists" exit 1 fi if ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e "SHOW DATABASES" | grep -E '^(syncstorage_rs|tokenserver_rs)$' > /dev/null 2>&1; then - echo "MySQL database(s) for ${SPK_NAME} already exist(s)" + echo "MySQL database(s) for ${DBUSER} already exist(s)" exit 1 fi - fi + fi fi } @@ -44,23 +47,23 @@ service_postinst () # login as root sql user using whatever creds you set up for that # this sets up a user for sync storage and sets up the databases ${MYSQL} -u root -p ${wizard_mysql_password_root} < Date: Sat, 2 Dec 2023 01:22:45 +0100 Subject: [PATCH 30/54] service-setup: cleanup merge errors, provide tools and merge resources --- cross/syncstorage-rs/Makefile | 13 +++++++++++++ cross/syncstorage-rs/PLIST | 3 +++ spk/ffsync/src/service-setup.sh | 7 +++---- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 29d26f55432..14a34d8d7f0 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -41,4 +41,17 @@ ENV += MYSQLCLIENT_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib # to find dependencies of libmysqlclient (libz) ENV += RUSTFLAGS="-Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib -Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib" +POST_INSTALL_TARGET = syncstorage-rs_post_install + include ../../mk/spksrc.cross-rust.mk + + +.PHONY: syncstorage-rs_post_install +syncstorage-rs_post_install: + @$(MSG) Install Tools + @install -m 755 -d $(STAGING_INSTALL_PREFIX)/tools + @tar -cf - -C $(WORK_DIR)/$(PKG_DIR)/tools . | tar -xf - -C $(STAGING_INSTALL_PREFIX)/tools + @$(MSG) Install DB Migration scripts + @install -m 755 -d $(STAGING_INSTALL_PREFIX)/syncstorage-mysql/migrations -d $(STAGING_INSTALL_PREFIX)/tokenserver-db/migrations + @tar -cf - -C $(WORK_DIR)/$(PKG_DIR)/syncstorage-mysql/migrations . | tar -xf - -C $(STAGING_INSTALL_PREFIX)/syncstorage-mysql/migrations + @tar -cf - -C $(WORK_DIR)/$(PKG_DIR)/tokenserver-db/migrations . | tar -xf - -C $(STAGING_INSTALL_PREFIX)/tokenserver-db/migrations diff --git a/cross/syncstorage-rs/PLIST b/cross/syncstorage-rs/PLIST index 1a9c2bf8073..5e07c7dc11f 100644 --- a/cross/syncstorage-rs/PLIST +++ b/cross/syncstorage-rs/PLIST @@ -1 +1,4 @@ bin:bin/syncserver +rsc:tools/ +rsc:syncstorage-mysql/ +rsc:tokenserver-db/ diff --git a/spk/ffsync/src/service-setup.sh b/spk/ffsync/src/service-setup.sh index acbaac09e7f..adb38568dfa 100644 --- a/spk/ffsync/src/service-setup.sh +++ b/spk/ffsync/src/service-setup.sh @@ -57,13 +57,12 @@ EOF # Run initial database migrations # syncstorage db initialization ${DIESEL} --database-url "mysql://${DBUSER}:${wizard_password_ffsync}@localhost/syncstorage_rs" \ - migration --migration-dir syncstorage-mysql/migrations run + migration --migration-dir ${SYNOPKG_PKGDEST}/syncstorage-mysql/migrations run # tokenserver db initialization ${DIESEL} --database-url "mysql://${DBUSER}:${wizard_password_ffsync}@localhost/tokenserver_rs" \ - migration --migration-dir tokenserver-db/migrations run + migration --migration-dir ${SYNOPKG_PKGDEST}/tokenserver-db/migrations run # Add sync endpoint to database - ${MYSQL} -u ${SPK_NAME} -p"${wizard_password_ffsync}" < Date: Sat, 2 Dec 2023 02:23:28 -0400 Subject: [PATCH 31/54] Additional fixes --- spk/ffsync/src/service-setup.sh | 49 ++++++++++++++++++++++++++++----- spk/ffsync/src/var/local.toml | 4 +-- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/spk/ffsync/src/service-setup.sh b/spk/ffsync/src/service-setup.sh index adb38568dfa..42c534fe8ff 100644 --- a/spk/ffsync/src/service-setup.sh +++ b/spk/ffsync/src/service-setup.sh @@ -4,6 +4,7 @@ PATH="${SYNOPKG_PKGDEST}/env/bin:${SYNOPKG_PKGDEST}/bin:${PYTHON_DIR}:${PATH}" MARIADB_10_INSTALL_DIRECTORY="/var/packages/MariaDB10" MARIADB_10_BIN_DIRECTORY="${MARIADB_10_INSTALL_DIRECTORY}/target/usr/local/mariadb10/bin" MYSQL="${MARIADB_10_BIN_DIRECTORY}/mysql" +MYSQLDUMP="${MARIADB_10_BIN_DIRECTORY}/mysqldump" PYTHON="${SYNOPKG_PKGDEST}/env/bin/python3" SYNCSERVER="${SYNOPKG_PKGDEST}/bin/syncserver" @@ -13,6 +14,7 @@ CFG_FILE="${SYNOPKG_PKGVAR}/local.toml" SERVICE_COMMAND="${SYNCSERVER} --config=${CFG_FILE}" DBUSER=ffsync +DBSERVER="127.0.0.1" validate_preinst () { @@ -56,24 +58,26 @@ EOF # Run initial database migrations # syncstorage db initialization - ${DIESEL} --database-url "mysql://${DBUSER}:${wizard_password_ffsync}@localhost/syncstorage_rs" \ + ${DIESEL} --database-url "mysql://${DBUSER}:${wizard_password_ffsync}@${DBSERVER}/syncstorage_rs" \ migration --migration-dir ${SYNOPKG_PKGDEST}/syncstorage-mysql/migrations run # tokenserver db initialization - ${DIESEL} --database-url "mysql://${DBUSER}:${wizard_password_ffsync}@localhost/tokenserver_rs" \ + ${DIESEL} --database-url "mysql://${DBUSER}:${wizard_password_ffsync}@${DBSERVER}/tokenserver_rs" \ migration --migration-dir ${SYNOPKG_PKGDEST}/tokenserver-db/migrations run # Add sync endpoint to database - ${MYSQL} -u ${DBUSER} -p"$(wizard_password_ffsync)" < /dev/null 2>&1; then + echo "Incorrect MySQL root password" + exit 1 + fi + # Check database export location + if [ "${SYNOPKG_PKG_STATUS}" = "UNINSTALL" ] && [ -n "${wizard_dbexport_path}" ]; then + if [ -f "${wizard_dbexport_path}" ] || [ -e "${wizard_dbexport_path}/${DBUSER}.sql" ]; then + echo "File ${wizard_dbexport_path}/${DBUSER}.sql already exists. Please remove or choose a different location" + exit 1 + fi + fi +} + +service_postuninst () +{ + # Export and remove database + if [ "${SYNOPKG_PKG_STATUS}" = "UNINSTALL" ]; then + if [ -n "${wizard_dbexport_path}" ]; then + mkdir -p ${wizard_dbexport_path} + ${MYSQLDUMP} -u root -p"${wizard_mysql_password_root}" ${DBUSER} > ${wizard_dbexport_path}/${DBUSER}.sql + fi + ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e "DROP DATABASE syncstorage_rs; DROP DATABASE tokenserver_rs; DROP USER '${DBUSER}'@'localhost';" + fi + + exit 0 +} diff --git a/spk/ffsync/src/var/local.toml b/spk/ffsync/src/var/local.toml index 98d9cfcdf95..0b00ac08752 100644 --- a/spk/ffsync/src/var/local.toml +++ b/spk/ffsync/src/var/local.toml @@ -6,13 +6,13 @@ human_logs = 1 host = "localhost" # default port = {{TCP_PORT}} # SPK default -syncstorage.database_url = "mysql://{{SQL_USER}}:{{SQL_PASS}}@localhost/syncstorage_rs" +syncstorage.database_url = "mysql://{{SQL_USER}}:{{SQL_PASS}}@{{DB_SERVER}}/syncstorage_rs" syncstorage.enable_quota = 0 syncstorage.enabled = true syncstorage.limits.max_total_records = 1666 # See issues #298/#333 # token -tokenserver.database_url = "mysql://{{SQL_USER}}:{{SQL_PASS}}@localhost/tokenserver_rs" +tokenserver.database_url = "mysql://{{SQL_USER}}:{{SQL_PASS}}@{{DB_SERVER}}/tokenserver_rs" tokenserver.enabled = true tokenserver.fxa_email_domain = "api.accounts.firefox.com" tokenserver.fxa_metrics_hash_secret = "{{METRICS_HASH_SECRET}}" From 6dd3e830136d626e49f196e0eceb0e517219da31 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Sat, 2 Dec 2023 10:52:49 -0400 Subject: [PATCH 32/54] Fix for build exclusions and uninstall --- cross/syncstorage-rs/Makefile | 5 ++--- spk/ffsync/Makefile | 1 - spk/ffsync/src/wizard/uninstall_uifile.sh | 7 +++++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 14a34d8d7f0..06f9c40e248 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -12,8 +12,8 @@ DEPENDS = cross/openssl3 # for mysqlclient-sys DEPENDS += cross/mysql-connector-c -# powerpc archs (except qoriq) are not supported -UNSUPPORTED_ARCHS += $(OLD_PPC_ARCHS) +# powerpc archs are not supported +UNSUPPORTED_ARCHS += $(PPC_ARCHS) HOMEPAGE = https://github.com/mozilla-services/syncstorage-rs/ COMMENT = Mozilla Sync Storage built with Rust. @@ -45,7 +45,6 @@ POST_INSTALL_TARGET = syncstorage-rs_post_install include ../../mk/spksrc.cross-rust.mk - .PHONY: syncstorage-rs_post_install syncstorage-rs_post_install: @$(MSG) Install Tools diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index 87fae804026..a45ce6a0907 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -40,7 +40,6 @@ ADMIN_PORT = $(SERVICE_PORT) # with C instead. This env var is only present in cryptography<3.5. ENV += CRYPTOGRAPHY_DONT_BUILD_RUST=1 - # [mysqlclient] ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" diff --git a/spk/ffsync/src/wizard/uninstall_uifile.sh b/spk/ffsync/src/wizard/uninstall_uifile.sh index 6f041864b75..3014c266a33 100644 --- a/spk/ffsync/src/wizard/uninstall_uifile.sh +++ b/spk/ffsync/src/wizard/uninstall_uifile.sh @@ -59,6 +59,13 @@ PAGE_FFSYNC_REMOVE=$(/bin/cat< Date: Sat, 2 Dec 2023 11:31:31 -0400 Subject: [PATCH 33/54] Amendments to fixes --- cross/diesel/Makefile | 2 +- cross/syncstorage-rs/Makefile | 2 +- spk/ffsync/Makefile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cross/diesel/Makefile b/cross/diesel/Makefile index 9e7abb0b8ca..5fe91a5d1f9 100644 --- a/cross/diesel/Makefile +++ b/cross/diesel/Makefile @@ -23,6 +23,6 @@ CARGO_BUILD_ARGS += --features=mysql # mysqlclient-sys: to find libmysqlclient ENV += MYSQLCLIENT_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib # to find dependencies of libmysqlclient (libz) -ENV += RUSTFLAGS="-Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib -Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib" +ENV += RUSTFLAGS="-Clink-arg=-Wl,--rpath,$(STAGING_INSTALL_PREFIX)/lib -Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib" include ../../mk/spksrc.cross-rust.mk diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 06f9c40e248..674c3a35d59 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -39,7 +39,7 @@ endif # mysqlclient-sys: to find libmysqlclient ENV += MYSQLCLIENT_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib # to find dependencies of libmysqlclient (libz) -ENV += RUSTFLAGS="-Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib -Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib" +ENV += RUSTFLAGS="-Clink-arg=-Wl,--rpath,$(STAGING_INSTALL_PREFIX)/lib -Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib" POST_INSTALL_TARGET = syncstorage-rs_post_install diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index a45ce6a0907..a78273e5581 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -8,7 +8,7 @@ DEPENDS = cross/syncstorage-rs cross/diesel PYTHON_PACKAGE = python311 WHEELS = src/requirements-crossenv.txt src/requirements-pure.txt -UNSUPPORTED_ARCHS = $(ARMv5_ARCHS) $(OLD_PPC_ARCHS) +UNSUPPORTED_ARCHS = $(ARMv5_ARCHS) $(PPC_ARCHS) REQUIRED_MIN_DSM = 6.0 SPK_DEPENDS = MariaDB10:$(PYTHON_PACKAGE) From 654e0b336c2a017554a716167d8a4e92ae5ef524 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Sat, 2 Dec 2023 12:08:19 -0400 Subject: [PATCH 34/54] Amendments to fixes --- cross/diesel/Makefile | 2 +- cross/syncstorage-rs/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cross/diesel/Makefile b/cross/diesel/Makefile index 5fe91a5d1f9..52b938b3d57 100644 --- a/cross/diesel/Makefile +++ b/cross/diesel/Makefile @@ -23,6 +23,6 @@ CARGO_BUILD_ARGS += --features=mysql # mysqlclient-sys: to find libmysqlclient ENV += MYSQLCLIENT_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib # to find dependencies of libmysqlclient (libz) -ENV += RUSTFLAGS="-Clink-arg=-Wl,--rpath,$(STAGING_INSTALL_PREFIX)/lib -Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib" +ENV += RUSTFLAGS="-Clink-arg=-Wl,--rpath,$(INSTALL_PREFIX)/lib -Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib" include ../../mk/spksrc.cross-rust.mk diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 674c3a35d59..013e6ad8a22 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -39,7 +39,7 @@ endif # mysqlclient-sys: to find libmysqlclient ENV += MYSQLCLIENT_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib # to find dependencies of libmysqlclient (libz) -ENV += RUSTFLAGS="-Clink-arg=-Wl,--rpath,$(STAGING_INSTALL_PREFIX)/lib -Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib" +ENV += RUSTFLAGS="-Clink-arg=-Wl,--rpath,$(INSTALL_PREFIX)/lib -Clink-arg=-Wl,--rpath-link,$(STAGING_INSTALL_PREFIX)/lib" POST_INSTALL_TARGET = syncstorage-rs_post_install From 81ec41c93d7657cff079263af59ffbd78d12c02a Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Sat, 2 Dec 2023 12:25:02 -0400 Subject: [PATCH 35/54] Incorporating build suggestions --- cross/syncstorage-rs/Makefile | 2 +- spk/ffsync/Makefile | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 013e6ad8a22..07bb6dacbfd 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -8,7 +8,7 @@ PKG_DIR = $(PKG_NAME)-$(PKG_VERS) # only required for build in cross/syncstorage-rs folder (not when using prebuilt spk/python311) #BUILD_DEPENDS = cross/python311 # for openssl-sys -DEPENDS = cross/openssl3 +DEPENDS = cross/openssl cross/openssl3 # for mysqlclient-sys DEPENDS += cross/mysql-connector-c diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index a78273e5581..34208cb577e 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -5,13 +5,12 @@ SPK_ICON = src/ffsync.png DEPENDS = cross/syncstorage-rs cross/diesel -PYTHON_PACKAGE = python311 WHEELS = src/requirements-crossenv.txt src/requirements-pure.txt UNSUPPORTED_ARCHS = $(ARMv5_ARCHS) $(PPC_ARCHS) REQUIRED_MIN_DSM = 6.0 -SPK_DEPENDS = MariaDB10:$(PYTHON_PACKAGE) +SPK_DEPENDS = MariaDB10:python311 MAINTAINER = SynoCommunity DESCRIPTION = Firefox Sync Server 1.5, used for Firefox 29 and later. You can use Firefox Sync Server to synchronize your bookmarks, passwords, settings, history, add-ons and tabs with Firefox on other computers. The service runs on port 8132. @@ -46,7 +45,7 @@ ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" POST_STRIP_TARGET = ffsync_extra_install -include ../../mk/spksrc.python.mk +include ../../mk/spksrc.spk.mk .PHONY: ffsync_extra_install ffsync_extra_install: From 2aa2dd607d19820602c8a598f98e6875b7e2dd78 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Sat, 2 Dec 2023 14:55:37 -0400 Subject: [PATCH 36/54] Testing build options --- cross/syncstorage-rs/Makefile | 4 ++-- spk/ffsync/Makefile | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 07bb6dacbfd..893e067e6e2 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -6,9 +6,9 @@ PKG_DIST_SITE = https://github.com/mozilla-services/$(PKG_NAME)/archive/${PKG_VE PKG_DIR = $(PKG_NAME)-$(PKG_VERS) # only required for build in cross/syncstorage-rs folder (not when using prebuilt spk/python311) -#BUILD_DEPENDS = cross/python311 +BUILD_DEPENDS = cross/python311 # for openssl-sys -DEPENDS = cross/openssl cross/openssl3 +DEPENDS = cross/openssl3 # for mysqlclient-sys DEPENDS += cross/mysql-connector-c diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index 34208cb577e..026df46ac6f 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -4,6 +4,7 @@ SPK_REV = 4 SPK_ICON = src/ffsync.png DEPENDS = cross/syncstorage-rs cross/diesel +DEPENDS += cross/openssl WHEELS = src/requirements-crossenv.txt src/requirements-pure.txt From fc78bea3b84418616375c14731a2f526c1585f76 Mon Sep 17 00:00:00 2001 From: hgy59 Date: Sat, 2 Dec 2023 22:15:47 +0100 Subject: [PATCH 37/54] configure default mysql socket - mysql-connector-c: add option to configure default mysql socket - used mariadb10 socket as default for cross/diesel and syncstorage-rs --- cross/diesel/Makefile | 5 +++++ cross/mysql-connector-c/Makefile | 13 +++++++++++++ cross/syncstorage-rs/Makefile | 7 ++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/cross/diesel/Makefile b/cross/diesel/Makefile index 52b938b3d57..2a12d1381d8 100644 --- a/cross/diesel/Makefile +++ b/cross/diesel/Makefile @@ -20,6 +20,11 @@ RUST_SRC_DIR = $(WORK_DIR)/$(PKG_DIR)/diesel_cli CARGO_BUILD_ARGS += --no-default-features CARGO_BUILD_ARGS += --features=mysql +# we support MariaDB 10 only +# we must define the mysql db socket, since the rust binaries (mysqlclient-sys) +# do not read settings from bin/mysql_conf +export "MYSQL_DB_SOCKET=/run/mysqld/mysqld10.sock" + # mysqlclient-sys: to find libmysqlclient ENV += MYSQLCLIENT_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib # to find dependencies of libmysqlclient (libz) diff --git a/cross/mysql-connector-c/Makefile b/cross/mysql-connector-c/Makefile index e9f90a027a5..32c3726281b 100644 --- a/cross/mysql-connector-c/Makefile +++ b/cross/mysql-connector-c/Makefile @@ -19,6 +19,19 @@ include ../../mk/spksrc.cross-cmake.mk # give access to comp_err binary on host ENV += PATH=$(WORK_DIR)/../../../native/libmysqlclient/work-native/install/usr/local/bin/:$(CMAKE_PATH):$$PATH +# custom mysql socket addr (default is /tmp/mysql.sock) +# on DSM 7 (only MariaDB 10 available) +# /run/mysqld/mysqld10.sock (links to /run/mysqld/mysqld.sock) +# /run/mysqld/mysqld.sock +# on DSM 6 with mariadb 5 and 10 +# /run/mysqld/mysqld.sock (MariaDB 5) +# /run/mysqld/mysqld10.sock (MariaDB 10) +ifneq ($(MYSQL_DB_SOCKET),) +# default mysql socket for DSM +MYSQL_DB_SOCKET = /run/mysqld/mysqld.sock +endif +CMAKE_ARGS += -DMYSQL_UNIX_ADDR=$(MYSQL_DB_SOCKET) + # Mandatory for build CMAKE_ARGS += -DHAVE_LLVM_LIBCPP_EXITCODE=1 CMAKE_ARGS += -DHAVE_CXX_FLOATING_POINT_OPTIMIZATION_PROBLEMS_EXITCODE=1 diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 893e067e6e2..37cfbbda2cf 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -6,7 +6,7 @@ PKG_DIST_SITE = https://github.com/mozilla-services/$(PKG_NAME)/archive/${PKG_VE PKG_DIR = $(PKG_NAME)-$(PKG_VERS) # only required for build in cross/syncstorage-rs folder (not when using prebuilt spk/python311) -BUILD_DEPENDS = cross/python311 +#BUILD_DEPENDS = cross/python311 # for openssl-sys DEPENDS = cross/openssl3 # for mysqlclient-sys @@ -25,6 +25,11 @@ CARGO_BUILD_ARGS += --no-default-features CARGO_BUILD_ARGS += --features=syncstorage-db/mysql CARGO_BUILD_ARGS += --locked +# we support MariaDB 10 only +# we must define the mysql db socket, since the rust binaries (mysqlclient-sys) +# do not read settings from bin/mysql_conf +export MYSQL_DB_SOCKET=/run/mysqld/mysqld10.sock + # To find libpython in prebuilt or local built python ifneq ($(PYTHON_STAGING_PREFIX),) # use prebuilt python From 4445ad31f835685d9be0102fde06eac693f5d328 Mon Sep 17 00:00:00 2001 From: hgy59 Date: Sat, 2 Dec 2023 22:20:38 +0100 Subject: [PATCH 38/54] ffsync: use prebuilt python again and fix dependencies - use prebuilt python - use cryptography==41.0.3 (the original 3.4.8 does not work with openssl3) - add mandatory crossenv dependencies - add mandatory pure python dependencies --- spk/ffsync/Makefile | 17 ++++++++--------- spk/ffsync/src/requirements-crossenv.txt | 19 ++++++++++++++----- spk/ffsync/src/requirements-pure.txt | 21 ++++++++++++++++++--- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index 026df46ac6f..b026a7855b1 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -4,14 +4,14 @@ SPK_REV = 4 SPK_ICON = src/ffsync.png DEPENDS = cross/syncstorage-rs cross/diesel -DEPENDS += cross/openssl +PYTHON_PACKAGE = python311 WHEELS = src/requirements-crossenv.txt src/requirements-pure.txt UNSUPPORTED_ARCHS = $(ARMv5_ARCHS) $(PPC_ARCHS) REQUIRED_MIN_DSM = 6.0 -SPK_DEPENDS = MariaDB10:python311 +SPK_DEPENDS = MariaDB10:$(PYTHON_PACKAGE) MAINTAINER = SynoCommunity DESCRIPTION = Firefox Sync Server 1.5, used for Firefox 29 and later. You can use Firefox Sync Server to synchronize your bookmarks, passwords, settings, history, add-ons and tabs with Firefox on other computers. The service runs on port 8132. @@ -33,12 +33,11 @@ SERVICE_PORT_TITLE = $(DISPLAY_NAME) ADMIN_PORT = $(SERVICE_PORT) # [cryptography] -# We pin cryptography to 3.4.8 due to a build error that occurs with the -# current version (36.0.0 at the time of this commit). In short, building -# the cryptography package with Rust results in a segfault, so we need to -# set the CRYPTOGRAPHY_DONT_BUILD_RUST env var to force the package to build -# with C instead. This env var is only present in cryptography<3.5. -ENV += CRYPTOGRAPHY_DONT_BUILD_RUST=1 +# Mandatory of using OPENSSL_*_DIR starting with version >= 40 +# https://docs.rs/openssl/latest/openssl/#automatic +DEPENDS += cross/openssl3 +ENV += OPENSSL_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib/ +ENV += OPENSSL_INCLUDE_DIR=$(STAGING_INSTALL_PREFIX)/include/ # [mysqlclient] ENV += MYSQLCLIENT_CFLAGS="$(CFLAGS) -I$(STAGING_INSTALL_PREFIX)/include/mysql -I$(STAGING_INSTALL_PREFIX)/$(PYTHON_INC_DIR)" @@ -46,7 +45,7 @@ ENV += MYSQLCLIENT_LDFLAGS="$(LDFLAGS)" POST_STRIP_TARGET = ffsync_extra_install -include ../../mk/spksrc.spk.mk +include ../../mk/spksrc.python.mk .PHONY: ffsync_extra_install ffsync_extra_install: diff --git a/spk/ffsync/src/requirements-crossenv.txt b/spk/ffsync/src/requirements-crossenv.txt index de73d4d758d..a19da824b33 100644 --- a/spk/ffsync/src/requirements-crossenv.txt +++ b/spk/ffsync/src/requirements-crossenv.txt @@ -1,16 +1,19 @@ # From requirements.txt +# original dependency does not work with openssl3: # We pin cryptography to 3.4.8 due to a build error that occurs with the # current version (36.0.0 at the time of this commit). In short, building # the cryptography package with Rust results in a segfault, so we need to # set the CRYPTOGRAPHY_DONT_BUILD_RUST env var to force the package to build # with C instead. This env var is only present in cryptography<3.5. +#cryptography==3.4.8 -# [bcrypt] & [cryptography] -# Require environment variables -# PYO3_CROSS_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib/ -# PYO3_CROSS_INCLUDE_DIR=$(STAGING_INSTALL_PREFIX)/include/ -cryptography==3.4.8 +# [cryptography] +# Mandatory of using OPENSSL_*_DIR starting with version >= 40 +# https://docs.rs/openssl/latest/openssl/#automatic +# ENV += OPENSSL_LIB_DIR=$(STAGING_INSTALL_PREFIX)/lib/ +# ENV += OPENSSL_INCLUDE_DIR=$(STAGING_INSTALL_PREFIX)/include/ +cryptography==41.0.3 # From tools/tokenserver/requirements.txt @@ -22,3 +25,9 @@ cryptography==3.4.8 mysqlclient==2.1.1 sqlalchemy==1.4.46 + +# further crossenv dependencies +cffi==1.16.0 +charset_normalizer==3.3.2 +greenlet==3.0.1 +zope.interface==6.1 diff --git a/spk/ffsync/src/requirements-pure.txt b/spk/ffsync/src/requirements-pure.txt index 307c2b9abe1..732d747fe17 100644 --- a/spk/ffsync/src/requirements-pure.txt +++ b/spk/ffsync/src/requirements-pure.txt @@ -8,7 +8,22 @@ tokenlib==2.0.0 boto==2.49.0 hawkauthlib==2.0.0 pyramid==2.0.1 -sqlalchemy==1.4.46 -testfixtures -tokenlib==2.0.0 +#sqlalchemy==1.4.46 => crossenv +testfixtures==7.2.2 +#tokenlib==2.0.0 => same as above PyBrowserID==0.14.0 + + +# further dependencies +hupper==1.12 +idna==3.6 +PasteDeploy==3.1.0 +plaster==1.1.2 +plaster_pastedeploy==1.0.1 +PyJWT==2.8.0 +requests==2.31.0 +translationstring==1.4 +urllib3==2.1.0 +venusian==3.1.0 +WebOb==1.8.7 +zope.deprecation==5.0 From ebcf6de5a1dc9a3f96b05fcef2e2e6ff1ca99c3f Mon Sep 17 00:00:00 2001 From: hgy59 Date: Sat, 2 Dec 2023 22:22:46 +0100 Subject: [PATCH 39/54] fix host configuration --- spk/ffsync/src/var/local.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spk/ffsync/src/var/local.toml b/spk/ffsync/src/var/local.toml index 0b00ac08752..141e24dd3ca 100644 --- a/spk/ffsync/src/var/local.toml +++ b/spk/ffsync/src/var/local.toml @@ -3,8 +3,10 @@ master_secret = "{{MASTER_SECRET}}" # removing this line will default to moz_json formatted logs human_logs = 1 -host = "localhost" # default -port = {{TCP_PORT}} # SPK default +# required to be externally available +host = "0.0.0.0" +# defined by SynoCommunity Package +port = {{TCP_PORT}} syncstorage.database_url = "mysql://{{SQL_USER}}:{{SQL_PASS}}@{{DB_SERVER}}/syncstorage_rs" syncstorage.enable_quota = 0 From a65b8b7363049a3bce15d1666785732a79039ce4 Mon Sep 17 00:00:00 2001 From: hgy59 Date: Sat, 2 Dec 2023 22:25:21 +0100 Subject: [PATCH 40/54] fix service-setup - use syncserver in background and provide pid file - enhance service log - since mysql socket configuration is fixed, we can use localhost as DBSERVER again - use pip to install *.whl and package from index - enhance installer logs --- spk/ffsync/src/service-setup.sh | 46 +++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/spk/ffsync/src/service-setup.sh b/spk/ffsync/src/service-setup.sh index 42c534fe8ff..0b68890a833 100644 --- a/spk/ffsync/src/service-setup.sh +++ b/spk/ffsync/src/service-setup.sh @@ -12,9 +12,15 @@ DIESEL="${SYNOPKG_PKGDEST}/bin/diesel" CFG_FILE="${SYNOPKG_PKGVAR}/local.toml" SERVICE_COMMAND="${SYNCSERVER} --config=${CFG_FILE}" +SVC_BACKGROUND=y +SVC_WRITE_PID=y + +# enhance logging +export RUST_LOG=debug +export RUST_BACKTRACE=full DBUSER=ffsync -DBSERVER="127.0.0.1" +DBSERVER="localhost" validate_preinst () { @@ -39,13 +45,24 @@ validate_preinst () service_postinst () { - # Create a Python virtualenv + separator="====================================================" + + echo "Install Python virtual environment" install_python_virtualenv - # Install wheels - install_python_wheels + echo ${separator} + echo "Install packages from wheelhouse" + pip install --disable-pip-version-check --no-deps --no-input --no-index ${SYNOPKG_PKGDEST}/share/wheelhouse/*.whl + + echo ${separator} + echo "Install pure python packages from index" + pip install --disable-pip-version-check --no-deps --no-input --requirement ${SYNOPKG_PKGDEST}/share/wheelhouse/requirements-pure.txt + if [ "${SYNOPKG_PKG_STATUS}" = "INSTALL" ]; then + + echo ${separator} + echo "Set up the databases" # login as root sql user using whatever creds you set up for that # this sets up a user for sync storage and sets up the databases ${MYSQL} -u root -p"${wizard_mysql_password_root}" < Date: Sun, 3 Dec 2023 00:02:00 +0100 Subject: [PATCH 41/54] try to fix greenlet requirement --- spk/ffsync/Makefile | 11 +++++++++++ spk/ffsync/src/requirements-crossenv-greenlet-v1.txt | 9 +++++++++ spk/ffsync/src/requirements-crossenv-greenlet-v2.txt | 9 +++++++++ spk/ffsync/src/requirements-crossenv.txt | 2 +- 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 spk/ffsync/src/requirements-crossenv-greenlet-v1.txt create mode 100644 spk/ffsync/src/requirements-crossenv-greenlet-v2.txt diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index b026a7855b1..afe2eee6f03 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -47,6 +47,17 @@ POST_STRIP_TARGET = ffsync_extra_install include ../../mk/spksrc.python.mk +# [greenlet] +ifeq ($(call version_ge, $(TC_GCC), 4.9),1) +WHEELS += src/requirements-crossenv-greenlet-v2.txt +ifeq ($(call version_lt, $(TC_GCC), 5.0),1) +WHEELS_CPPFLAGS += [greenlet] -std=c++11 -fpermissive +endif +else +WHEELS += src/requirements-crossenv-greenlet-v1.txt +endif + + .PHONY: ffsync_extra_install ffsync_extra_install: @$(MSG) Install config file diff --git a/spk/ffsync/src/requirements-crossenv-greenlet-v1.txt b/spk/ffsync/src/requirements-crossenv-greenlet-v1.txt new file mode 100644 index 00000000000..eab2e8a8b4f --- /dev/null +++ b/spk/ffsync/src/requirements-crossenv-greenlet-v1.txt @@ -0,0 +1,9 @@ +## +## All configurations below are optional and +## are provided to demonstrate how to build +## various wheels. Uncoment to enable. +## + +# [greenlet] +# - gcc < 5.0 (DSM6) Last known working version +greenlet==1.1.3 diff --git a/spk/ffsync/src/requirements-crossenv-greenlet-v2.txt b/spk/ffsync/src/requirements-crossenv-greenlet-v2.txt new file mode 100644 index 00000000000..47a0d61c465 --- /dev/null +++ b/spk/ffsync/src/requirements-crossenv-greenlet-v2.txt @@ -0,0 +1,9 @@ +## +## All configurations below are optional and +## are provided to demonstrate how to build +## various wheels. Uncoment to enable. +## + +# [greenlet] +# - Mandatory require full c++11 support +greenlet==2.0.2 diff --git a/spk/ffsync/src/requirements-crossenv.txt b/spk/ffsync/src/requirements-crossenv.txt index a19da824b33..d74972f17ff 100644 --- a/spk/ffsync/src/requirements-crossenv.txt +++ b/spk/ffsync/src/requirements-crossenv.txt @@ -29,5 +29,5 @@ sqlalchemy==1.4.46 # further crossenv dependencies cffi==1.16.0 charset_normalizer==3.3.2 -greenlet==3.0.1 +# greenlet==3.0.1 => supported version depends on gcc version zope.interface==6.1 From 65f37a503157a972fdbc11a1157d9f47b1705485 Mon Sep 17 00:00:00 2001 From: hgy59 Date: Sun, 3 Dec 2023 10:33:48 +0100 Subject: [PATCH 42/54] fix mysql socket definition --- cross/mysql-connector-c/Makefile | 2 +- cross/syncstorage-rs/Makefile | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/cross/mysql-connector-c/Makefile b/cross/mysql-connector-c/Makefile index 32c3726281b..cd1da65ebc4 100644 --- a/cross/mysql-connector-c/Makefile +++ b/cross/mysql-connector-c/Makefile @@ -26,7 +26,7 @@ ENV += PATH=$(WORK_DIR)/../../../native/libmysqlclient/work-native/install/usr/l # on DSM 6 with mariadb 5 and 10 # /run/mysqld/mysqld.sock (MariaDB 5) # /run/mysqld/mysqld10.sock (MariaDB 10) -ifneq ($(MYSQL_DB_SOCKET),) +ifeq ($(MYSQL_DB_SOCKET),) # default mysql socket for DSM MYSQL_DB_SOCKET = /run/mysqld/mysqld.sock endif diff --git a/cross/syncstorage-rs/Makefile b/cross/syncstorage-rs/Makefile index 37cfbbda2cf..f81d9cb55ca 100644 --- a/cross/syncstorage-rs/Makefile +++ b/cross/syncstorage-rs/Makefile @@ -12,6 +12,13 @@ DEPENDS = cross/openssl3 # for mysqlclient-sys DEPENDS += cross/mysql-connector-c +# OLD_PPC_ARCHS are not supported for Rust builds +# Rust has support for qoriq, but the "ring" dependency has issue(s) with big-endian targets +# see: https://github.com/briansmith/ring/issues/1555 (and referenced issues) +# There is an update in https://github.com/briansmith/ring/pull/1677 for (64-bit) PPC +# this might fix ring for 32-bit PPC (qoriq) too. +# An update of ring (>= 0.17.0) is required, syncstorage-rs 0.14.3 has locked ring to 0.16.20. +# # powerpc archs are not supported UNSUPPORTED_ARCHS += $(PPC_ARCHS) From 51f1647d711d795f5daad62d90fc77aac790bbfd Mon Sep 17 00:00:00 2001 From: hgy59 Date: Sun, 3 Dec 2023 10:55:02 +0100 Subject: [PATCH 43/54] fix secret generation for DSM 6 - use base64 instead of base32 for secret generation --- spk/ffsync/src/service-setup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spk/ffsync/src/service-setup.sh b/spk/ffsync/src/service-setup.sh index 0b68890a833..b96bb76e7d2 100644 --- a/spk/ffsync/src/service-setup.sh +++ b/spk/ffsync/src/service-setup.sh @@ -102,8 +102,8 @@ EOF echo ${separator} echo "Setup syncserver config file" - MASTER_SECRET="$(cat /dev/urandom | base32 | head -c64)" - METRICS_HASH_SECRET="$(cat /dev/urandom | base32 | head -c64)" + MASTER_SECRET="$(cat /dev/urandom | base64 | head -c64)" + METRICS_HASH_SECRET="$(cat /dev/urandom | base64 | head -c64)" # Escape vertical bars in the replacement values WIZARD_PASSWORD=$(echo "${wizard_password_ffsync}" | sed 's/|/\\|/g') From aa249684d57e99c315c1bdcdf7515125b979a88b Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Sun, 3 Dec 2023 13:11:51 -0400 Subject: [PATCH 44/54] Fixes proposed after review --- spk/ffsync/src/service-setup.sh | 43 ++++++++++++++--------- spk/ffsync/src/wizard/install_uifile.sh | 39 ++------------------ spk/ffsync/src/wizard/uninstall_uifile.sh | 26 +++++++------- 3 files changed, 41 insertions(+), 67 deletions(-) diff --git a/spk/ffsync/src/service-setup.sh b/spk/ffsync/src/service-setup.sh index b96bb76e7d2..d7aee8cfeb1 100644 --- a/spk/ffsync/src/service-setup.sh +++ b/spk/ffsync/src/service-setup.sh @@ -60,13 +60,15 @@ service_postinst () if [ "${SYNOPKG_PKG_STATUS}" = "INSTALL" ]; then + # Generate database password for database user + DBPASS=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9!#$%^&*()_+{}<>?=' | fold -w 10 | grep -E '[a-z]' | grep -E '[A-Z]' | grep -E '[0-9]' | grep -E '[!#$%^&*()_+{}<>?=]' | head -n 1) echo ${separator} echo "Set up the databases" # login as root sql user using whatever creds you set up for that # this sets up a user for sync storage and sets up the databases ${MYSQL} -u root -p"${wizard_mysql_password_root}" < "${wizard_dbexport_path}/syncstorage_rs.sql" + ${MYSQLDUMP} -u root -p"${wizard_mysql_password_root}" tokenserver_rs > "${wizard_dbexport_path}/tokenserver_rs.sql" fi } @@ -139,10 +154,6 @@ service_postuninst () { # Export and remove database if [ "${SYNOPKG_PKG_STATUS}" = "UNINSTALL" ]; then - if [ -n "${wizard_dbexport_path}" ]; then - mkdir -p ${wizard_dbexport_path} - ${MYSQLDUMP} -u root -p"${wizard_mysql_password_root}" ${DBUSER} > ${wizard_dbexport_path}/${DBUSER}.sql - fi ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e "DROP DATABASE syncstorage_rs; DROP DATABASE tokenserver_rs; DROP USER '${DBUSER}'@'localhost';" fi } diff --git a/spk/ffsync/src/wizard/install_uifile.sh b/spk/ffsync/src/wizard/install_uifile.sh index 65591bb87ea..80674903b62 100644 --- a/spk/ffsync/src/wizard/install_uifile.sh +++ b/spk/ffsync/src/wizard/install_uifile.sh @@ -16,30 +16,6 @@ page_append () fi } -getRootPasswordValidator() -{ - validator=$(/bin/cat< Date: Sun, 3 Dec 2023 20:08:55 -0400 Subject: [PATCH 45/54] Final code cleanup --- spk/ffsync/Makefile | 4 +- spk/ffsync/src/TO_REMOVE/BROKEN | 8 - spk/ffsync/src/TO_REMOVE/PKG_DEPS | 5 - spk/ffsync/src/TO_REMOVE/dsm-control.sh | 90 ---------- spk/ffsync/src/TO_REMOVE/ffsync.ini | 45 ----- spk/ffsync/src/TO_REMOVE/ffsync.sc | 6 - spk/ffsync/src/TO_REMOVE/installer.sh | 168 ------------------ spk/ffsync/src/TO_REMOVE/requirements-all.txt | 21 --- spk/ffsync/src/service-setup.sh | 34 ++-- spk/ffsync/src/wizard/install_uifile.sh | 41 ++++- 10 files changed, 63 insertions(+), 359 deletions(-) delete mode 100644 spk/ffsync/src/TO_REMOVE/BROKEN delete mode 100644 spk/ffsync/src/TO_REMOVE/PKG_DEPS delete mode 100755 spk/ffsync/src/TO_REMOVE/dsm-control.sh delete mode 100755 spk/ffsync/src/TO_REMOVE/ffsync.ini delete mode 100644 spk/ffsync/src/TO_REMOVE/ffsync.sc delete mode 100755 spk/ffsync/src/TO_REMOVE/installer.sh delete mode 100644 spk/ffsync/src/TO_REMOVE/requirements-all.txt diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index afe2eee6f03..1dc6b5f5c7f 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -1,6 +1,6 @@ SPK_NAME = ffsync SPK_VERS = 0.14.3 -SPK_REV = 4 +SPK_REV = 1 SPK_ICON = src/ffsync.png DEPENDS = cross/syncstorage-rs cross/diesel @@ -16,7 +16,7 @@ SPK_DEPENDS = MariaDB10:$(PYTHON_PACKAGE) MAINTAINER = SynoCommunity DESCRIPTION = Firefox Sync Server 1.5, used for Firefox 29 and later. You can use Firefox Sync Server to synchronize your bookmarks, passwords, settings, history, add-ons and tabs with Firefox on other computers. The service runs on port 8132. DISPLAY_NAME = Firefox Sync Server 1.5 -CHANGELOG = "1. Upgrade to Mozilla Sync Storage built with Rust." +CHANGELOG = "Inital Mozilla Sync Storage package." HOMEPAGE = https://mozilla-services.readthedocs.io/en/latest/howtos/run-sync-1.5.html LICENSE = MPL 2.0 diff --git a/spk/ffsync/src/TO_REMOVE/BROKEN b/spk/ffsync/src/TO_REMOVE/BROKEN deleted file mode 100644 index e05071f7305..00000000000 --- a/spk/ffsync/src/TO_REMOVE/BROKEN +++ /dev/null @@ -1,8 +0,0 @@ -something is wrong with python2 wheels: - - make[3]: Leaving directory '/github/workspace/spk/ffsync' -===> [https://github.com/mozilla-services/tokenserver/archive/1.5.11.tar.gz] -make[3]: Entering directory '/github/workspace/spk/ffsync' -make[3]: *** No rule to make target 'cross-compile-wheel-https://github.com/mozilla-services/tokenserver/archive/1.5.11.tar.gz'. Stop. -make[3]: Leaving directory '/github/workspace/spk/ffsync' - diff --git a/spk/ffsync/src/TO_REMOVE/PKG_DEPS b/spk/ffsync/src/TO_REMOVE/PKG_DEPS deleted file mode 100644 index 265c6fd5421..00000000000 --- a/spk/ffsync/src/TO_REMOVE/PKG_DEPS +++ /dev/null @@ -1,5 +0,0 @@ -[MariaDB] -dsm_min_ver=5.0-4300 - -[python] -pkg_min_ver=2.7.8-9 diff --git a/spk/ffsync/src/TO_REMOVE/dsm-control.sh b/spk/ffsync/src/TO_REMOVE/dsm-control.sh deleted file mode 100755 index 51ab9dcebf8..00000000000 --- a/spk/ffsync/src/TO_REMOVE/dsm-control.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/sh - -# Package -PACKAGE="ffsync" -DNAME="Firefox Sync Server 1.5" - -# Others -INSTALL_DIR="/usr/local/${PACKAGE}" -PATH="${INSTALL_DIR}/env/bin:${INSTALL_DIR}/bin:${PYTHON_DIR}/bin:${PATH}" -BUILDNUMBER="$(/bin/get_key_value /etc.defaults/VERSION buildnumber)" -PSERVE="${INSTALL_DIR}/env/bin/pserve" -INI_FILE="${INSTALL_DIR}/var/ffsync.ini" -PID_FILE="${INSTALL_DIR}/var/ffsync.pid" -LOG_FILE="${INSTALL_DIR}/var/pserve.log" - -SC_USER="sc-ffsync" -LEGACY_USER="ffsync" -USER="$([ "${BUILDNUMBER}" -ge "7321" ] && echo -n ${SC_USER} || echo -n ${LEGACY_USER})" - - -start_daemon () -{ - ${PSERVE} ${INI_FILE} --user=${USER} --daemon --pid-file=${PID_FILE} --log-file=${LOG_FILE} - sleep 1 -} - -stop_daemon () -{ - ${PSERVE} ${INI_FILE} --stop-daemon --pid-file=${PID_FILE} --log-file=${LOG_FILE} -} - -daemon_status () -{ - if [ -f ${PID_FILE} ] && kill -0 `cat ${PID_FILE}` > /dev/null 2>&1; then - return - fi - rm -f ${PID_FILE} - return 1 -} - -wait_for_status () -{ - counter=$2 - while [ ${counter} -gt 0 ]; do - daemon_status - [ $? -eq $1 ] && return - let counter=counter-1 - sleep 1 - done - return 1 -} - - -case $1 in - start) - if daemon_status; then - echo ${DNAME} is already running - exit 0 - else - echo Starting ${DNAME} ... - start_daemon - exit $? - fi - ;; - stop) - if daemon_status; then - echo Stopping ${DNAME} ... - stop_daemon - exit $? - else - echo ${DNAME} is not running - exit 0 - fi - ;; - status) - if daemon_status; then - echo ${DNAME} is running - exit 0 - else - echo ${DNAME} is not running - exit 1 - fi - ;; - log) - echo ${LOG_FILE} - ;; - *) - exit 1 - ;; -esac diff --git a/spk/ffsync/src/TO_REMOVE/ffsync.ini b/spk/ffsync/src/TO_REMOVE/ffsync.ini deleted file mode 100755 index 753bf5b9809..00000000000 --- a/spk/ffsync/src/TO_REMOVE/ffsync.ini +++ /dev/null @@ -1,45 +0,0 @@ -[server:main] -use = egg:Paste#http -host = 0.0.0.0 -port = 8132 - -[app:main] -use = egg:syncserver - -[syncserver] -# This must be edited to point to the public URL of your server, -# i.e. the URL as seen by Firefox. -public_url = http://0.0.0.0:8132/ - -# This defines the database in which to store all server data. -#sqluri = sqlite:////tmp/syncserver.db -sqluri = pymysql://ffsync:@mysql_password@@localhost:3306/ffsync - -# This is a secret key used for signing authentication tokens. -# It should be long and randomly-generated. -# The following command will give a suitable value on *nix systems: -# -# head -c 20 /dev/urandom | sha1sum -# -# If not specified then the server will generate a temporary one at startup. -#secret = INSERT_SECRET_KEY_HERE - -# Set this to "false" to disable new-user signups on the server. -# Only request by existing accounts will be honoured. -# allow_new_users = false - -# Set this to "true" to work around a mismatch between public_url and -# the application URL as seen by python, which can happen in certain reverse- -# proxy hosting setups. It will overwrite the WSGI environ dict with the -# details from public_url. This could have security implications if e.g. -# you tell the app that it's on HTTPS but it's really on HTTP, so it should -# only be used as a last resort and after careful checking of server config. -force_wsgi_environ = false - -# Uncomment and edit the following to use a local BrowserID verifier -# rather than posting assertions to the mozilla-hosted verifier. -# Audiences should be set to your public_url without a trailing slash. -#[browserid] -#backend = tokenserver.verifiers.LocalVerifier -#audiences = https://localhost:5000 - diff --git a/spk/ffsync/src/TO_REMOVE/ffsync.sc b/spk/ffsync/src/TO_REMOVE/ffsync.sc deleted file mode 100644 index 7b5d5c9f4fa..00000000000 --- a/spk/ffsync/src/TO_REMOVE/ffsync.sc +++ /dev/null @@ -1,6 +0,0 @@ -[ffsync_port] -title="Firefox Sync Server 1.5" -desc="Firefox Sync Server 1.5" -port_forward="yes" -dst.ports="8132/tcp" - diff --git a/spk/ffsync/src/TO_REMOVE/installer.sh b/spk/ffsync/src/TO_REMOVE/installer.sh deleted file mode 100755 index ad808a4b2fa..00000000000 --- a/spk/ffsync/src/TO_REMOVE/installer.sh +++ /dev/null @@ -1,168 +0,0 @@ -#!/bin/sh - -# Package -PACKAGE="ffsync" -DNAME="Firefox Sync Server 1.5" - -# Others -INSTALL_DIR="/usr/local/${PACKAGE}" -SSS="/var/packages/${PACKAGE}/scripts/start-stop-status" -PYTHON_DIR="/usr/local/python" -PATH="${INSTALL_DIR}/env/bin:${INSTALL_DIR}/bin:${PYTHON_DIR}/bin:${PATH}" -VIRTUALENV="${PYTHON_DIR}/bin/virtualenv" -TMP_DIR="${SYNOPKG_PKGDEST}/../../@tmp" -SERVICETOOL="/usr/syno/bin/servicetool" -BUILDNUMBER="$(/bin/get_key_value /etc.defaults/VERSION buildnumber)" -FWPORTS="/var/packages/${PACKAGE}/scripts/${PACKAGE}.sc" -MYSQL="$([ "${BUILDNUMBER}" -ge "7321" ] && echo -n /bin/mysql || echo -n /usr/syno/mysql/bin/mysql)" -MYSQLDUMP="$([ "${BUILDNUMBER}" -ge "7321" ] && echo -n /bin/mysqldump || echo -n /usr/syno/mysql/bin/mysqldump)" -INI_FILE="${INSTALL_DIR}/var/ffsync.ini" - -DSM6_UPGRADE="${INSTALL_DIR}/var/.dsm6_upgrade" -SC_USER="sc-ffsync" -LEGACY_USER="ffsync" -LEGACY_GROUP="nobody" -USER="$([ "${BUILDNUMBER}" -ge "7321" ] && echo -n ${SC_USER} || echo -n ${LEGACY_USER})" - - -preinst () -{ - # Check MySQL database - if [ "${SYNOPKG_PKG_STATUS}" == "INSTALL" ]; then - if [ ! -z "${wizard_mysql_password_root}" ]; then - if ! ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e quit > /dev/null 2>&1; then - echo "Incorrect MySQL root password" - exit 1 - fi - if ${MYSQL} -u root -p"${wizard_mysql_password_root}" mysql -e "SELECT User FROM user" | grep ^${USER}$ > /dev/null 2>&1; then - echo "MySQL user ${USER} already exists" - exit 1 - fi - if ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e "SHOW DATABASES" | grep ^${PACKAGE}$ > /dev/null 2>&1; then - echo "MySQL database ${PACKAGE} already exists" - exit 1 - fi - fi - fi - - exit 0 -} - -postinst () -{ - # Link - ln -s ${SYNOPKG_PKGDEST} ${INSTALL_DIR} - - # Create conf dir for 4.3 and add dependencies - mkdir -p /var/packages/${PACKAGE}/conf && echo -e "[MariaDB]\ndsm_min_ver=5.0-4300\n\n[python]\npkg_min_ver=2.7.8-9" > /var/packages/${PACKAGE}/conf/PKG_DEPS - - # Install busybox stuff - ${INSTALL_DIR}/bin/busybox --install ${INSTALL_DIR}/bin - - # Edit the configuration according to the wizard - if [ "${SYNOPKG_PKG_STATUS}" == "INSTALL" ]; then - ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e "CREATE DATABASE ${PACKAGE}; GRANT ALL PRIVILEGES ON ${PACKAGE}.* TO '${USER}'@'localhost' IDENTIFIED BY '${wizard_password_ffsync:=ffsync}';" - sed -i -e "s|@mysql_password@|${wizard_password_ffsync:=ffsync}|g" \ - -e "s|^#secret.*|secret = `openssl rand -base64 20`|g" \ - -e "s|http://0.0.0.0:8132|http://${wizard_ffsync_public_url}:8132|g" \ - ${INI_FILE} - fi - - # Create a Python virtualenv - ${VIRTUALENV} --system-site-packages ${INSTALL_DIR}/env > /dev/null - - # Install the wheels - ${INSTALL_DIR}/env/bin/pip install --no-deps --no-index -U --force-reinstall -f ${INSTALL_DIR}/share/wheelhouse ${INSTALL_DIR}/share/wheelhouse/*.whl > /dev/null 2>&1 - - # Add port-forwarding config - ${SERVICETOOL} --install-configure-file --package ${FWPORTS} >> /dev/null - - # Create legacy user - if [ "${BUILDNUMBER}" -lt "7321" ]; then - adduser -h ${INSTALL_DIR}/var -g "${DNAME} User" -G ${LEGACY_GROUP} -s /bin/sh -S -D ${LEGACY_USER} - fi - - # Correct the files ownership - chown -R ${USER}:root ${SYNOPKG_PKGDEST} - - exit 0 -} - -preuninst () -{ - - # Check database - if [ "${SYNOPKG_PKG_STATUS}" == "UNINSTALL" ] && ! ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e quit > /dev/null 2>&1; then - echo "Incorrect MySQL root password" - exit 1 - fi - - # Check database export location - if [ "${SYNOPKG_PKG_STATUS}" == "UNINSTALL" -a -n "${wizard_dbexport_path}" ]; then - if [ -f "${wizard_dbexport_path}" -o -e "${wizard_dbexport_path}/${PACKAGE}.sql" ]; then - echo "File ${wizard_dbexport_path}/${PACKAGE}.sql already exists. Please remove or choose a different location" - exit 1 - fi - fi - - # Stop the package - ${SSS} stop > /dev/null - - if [ "${SYNOPKG_PKG_STATUS}" != "UPGRADE" ]; then - # Remove the user (if not upgrading) - delgroup ${LEGACY_USER} ${LEGACY_GROUP} - deluser ${USER} - - # Remove firewall configuration - ${SERVICETOOL} --remove-configure-file --package ${PACKAGE}.sc >> /dev/null - fi - - exit 0 -} - -postuninst () -{ - # Remove link - rm -f ${INSTALL_DIR} - - # Export and remove database - if [ "${SYNOPKG_PKG_STATUS}" == "UNINSTALL" ]; then - if [ -n "${wizard_dbexport_path}" ]; then - mkdir -p ${wizard_dbexport_path} - ${MYSQLDUMP} -u root -p"${wizard_mysql_password_root}" ${PACKAGE} > ${wizard_dbexport_path}/${PACKAGE}.sql - fi - ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e "DROP DATABASE ${PACKAGE}; DROP LEGACY_USER '${LEGACY_USER}'@'localhost';" - fi - - exit 0 -} - -preupgrade () -{ - # Stop the package - ${SSS} stop > /dev/null - - # DSM6 Upgrade handling - if [ "${BUILDNUMBER}" -ge "7321" ] && [ ! -f ${DSM6_UPGRADE} ]; then - echo "Deleting legacy user" > ${DSM6_UPGRADE} - delgroup ${LEGACY_USER} ${LEGACY_GROUP} - deluser ${LEGACY_USER} - fi - - # Save some stuff - rm -fr ${TMP_DIR}/${PACKAGE} - mkdir -p ${TMP_DIR}/${PACKAGE} - mv ${INSTALL_DIR}/var ${TMP_DIR}/${PACKAGE}/ - - exit 0 -} - -postupgrade () -{ - # Restore some stuff - rm -fr ${INSTALL_DIR}/var - mv ${TMP_DIR}/${PACKAGE}/var ${INSTALL_DIR}/ - rm -fr ${TMP_DIR}/${PACKAGE} - - exit 0 -} diff --git a/spk/ffsync/src/TO_REMOVE/requirements-all.txt b/spk/ffsync/src/TO_REMOVE/requirements-all.txt deleted file mode 100644 index 1dce0f3374e..00000000000 --- a/spk/ffsync/src/TO_REMOVE/requirements-all.txt +++ /dev/null @@ -1,21 +0,0 @@ -# From requirements.txt - -# We pin cryptography to 3.4.8 due to a build error that occurs with the -# current version (36.0.0 at the time of this commit). In short, building -# the cryptography package with Rust results in a segfault, so we need to -# set the CRYPTOGRAPHY_DONT_BUILD_RUST env var to force the package to build -# with C instead. This env var is only present in cryptography<3.5. -cryptography==3.4.8 -pyfxa==0.7.7 -tokenlib==2.0.0 - -# From tools/tokenserver/requirements.txt - -boto==2.49.0 -hawkauthlib==2.0.0 -mysqlclient==2.1.1 -pyramid==2.0.1 -sqlalchemy==1.4.46 -testfixtures -tokenlib==2.0.0 -PyBrowserID==0.14.0 diff --git a/spk/ffsync/src/service-setup.sh b/spk/ffsync/src/service-setup.sh index d7aee8cfeb1..57796333521 100644 --- a/spk/ffsync/src/service-setup.sh +++ b/spk/ffsync/src/service-setup.sh @@ -15,13 +15,24 @@ SERVICE_COMMAND="${SYNCSERVER} --config=${CFG_FILE}" SVC_BACKGROUND=y SVC_WRITE_PID=y -# enhance logging -export RUST_LOG=debug -export RUST_BACKTRACE=full - DBUSER=ffsync DBSERVER="localhost" +percent_encode () +{ + string="$1" + result="" + for ((i = 0; i < ${#string}; i++)); do + char="${string:$i:1}" + if [[ "$char" =~ [0-9a-zA-Z] ]]; then + result+="$char" + else + result+="$(printf '%%%02X' "'$char")" + fi + done + echo "$result" +} + validate_preinst () { # Check MySQL database @@ -61,14 +72,15 @@ service_postinst () if [ "${SYNOPKG_PKG_STATUS}" = "INSTALL" ]; then # Generate database password for database user - DBPASS=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9!#$%^&*()_+{}<>?=' | fold -w 10 | grep -E '[a-z]' | grep -E '[A-Z]' | grep -E '[0-9]' | grep -E '[!#$%^&*()_+{}<>?=]' | head -n 1) + DBPASS_RAW=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9!@#$%^&*()_+{}<>?=' | fold -w 10 | grep -E '[a-z]' | grep -E '[A-Z]' | grep -E '[0-9]' | grep -E '[!@#$%^&*()_+{}<>?=]' | head -n 1) + DBPASS_ENC=$(percent_encode "$DBPASS_RAW") echo ${separator} echo "Set up the databases" # login as root sql user using whatever creds you set up for that # this sets up a user for sync storage and sets up the databases ${MYSQL} -u root -p"${wizard_mysql_password_root}" <
http://public-url:8132/token/1.0/sync/1.5

Note: Configure a reverse proxy for SSL support", + "desc": "Please provide the client-visible URL. If utilizing a domain, ensure it follows the format http://hostname.domain:8132", "subitems": [{ "key": "wizard_ffsync_public_url", "desc": "Public URL", - "emptyText": "http://hostname.domain:8132", + "defaultValue": "http://${INTERNAL_IP}:8132", "validator": { - "allowBlank": false + "fn": "$(checkPublicUrl)" } }] + }, { + "type": "textfield", + "desc": "To configure your Firefox browser, go to about:config. Change identity.sync.tokenserver.uri the following URL:", + "subitems": [{ + "key": "client_ffsync_public_url", + "grow": true + }] + }, { + "desc": "Note: For SSL support, set up a reverse proxy" }] } EOF From 40f2b9544ff24cee90a072250e5aea10298eeb61 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Sun, 3 Dec 2023 21:45:39 -0400 Subject: [PATCH 46/54] Amend code cleanup 1. Make scripts more POSIX compatible 2. Move from base64 as character set can conflict with sed 3. Re-introduce enhanced logging --- spk/ffsync/src/service-setup.sh | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/spk/ffsync/src/service-setup.sh b/spk/ffsync/src/service-setup.sh index 57796333521..0524f91b897 100644 --- a/spk/ffsync/src/service-setup.sh +++ b/spk/ffsync/src/service-setup.sh @@ -15,6 +15,10 @@ SERVICE_COMMAND="${SYNCSERVER} --config=${CFG_FILE}" SVC_BACKGROUND=y SVC_WRITE_PID=y +# enhance logging +export RUST_LOG=debug +export RUST_BACKTRACE=full + DBUSER=ffsync DBSERVER="localhost" @@ -22,13 +26,16 @@ percent_encode () { string="$1" result="" - for ((i = 0; i < ${#string}; i++)); do - char="${string:$i:1}" - if [[ "$char" =~ [0-9a-zA-Z] ]]; then - result+="$char" + len=$(echo "$string" | awk '{print length}') + i=1 + while [ "$i" -le "$len" ]; do + char=$(echo "$string" | cut -c "$i") + if echo "$char" | grep -qE '[0-9a-zA-Z]'; then + result="$result$char" else - result+="$(printf '%%%02X' "'$char")" + result="$result$(printf '%%%02X' "'$char")" fi + i=$((i + 1)) done echo "$result" } @@ -63,16 +70,16 @@ service_postinst () echo ${separator} echo "Install packages from wheelhouse" - pip install --disable-pip-version-check --no-deps --no-input --no-index ${SYNOPKG_PKGDEST}/share/wheelhouse/*.whl + pip install --disable-pip-version-check --no-deps --no-input --no-index "${SYNOPKG_PKGDEST}/share/wheelhouse"/*.whl echo ${separator} echo "Install pure python packages from index" - pip install --disable-pip-version-check --no-deps --no-input --requirement ${SYNOPKG_PKGDEST}/share/wheelhouse/requirements-pure.txt + pip install --disable-pip-version-check --no-deps --no-input --requirement "${SYNOPKG_PKGDEST}/share/wheelhouse/requirements-pure.txt" if [ "${SYNOPKG_PKG_STATUS}" = "INSTALL" ]; then # Generate database password for database user - DBPASS_RAW=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9!@#$%^&*()_+{}<>?=' | fold -w 10 | grep -E '[a-z]' | grep -E '[A-Z]' | grep -E '[0-9]' | grep -E '[!@#$%^&*()_+{}<>?=]' | head -n 1) + DBPASS_RAW=$(tr -dc 'a-zA-Z0-9!@#$%^&*()_+{}<>?=' ?=]' | head -n 1) DBPASS_ENC=$(percent_encode "$DBPASS_RAW") echo ${separator} @@ -92,11 +99,11 @@ EOF echo "Run migrations for syncstorage_rs" ${DIESEL} --database-url "mysql://${DBUSER}:${DBPASS_ENC}@${DBSERVER}/syncstorage_rs" \ - migration --migration-dir ${SYNOPKG_PKGDEST}/syncstorage-mysql/migrations run + migration --migration-dir "${SYNOPKG_PKGDEST}/syncstorage-mysql/migrations" run echo "Run migrations for tokenserver_rs" ${DIESEL} --database-url "mysql://${DBUSER}:${DBPASS_ENC}@${DBSERVER}/tokenserver_rs" \ - migration --migration-dir ${SYNOPKG_PKGDEST}/tokenserver-db/migrations run + migration --migration-dir "${SYNOPKG_PKGDEST}/tokenserver-db/migrations" run echo ${separator} echo "Add sync endpoint to database" @@ -116,8 +123,8 @@ EOF echo ${separator} echo "Setup syncserver config file" - MASTER_SECRET="$(cat /dev/urandom | base64 | head -c64)" - METRICS_HASH_SECRET="$(cat /dev/urandom | base64 | head -c64)" + MASTER_SECRET="$(tr -dc 'A-Z0-9' < /dev/urandom | head -c64)" + METRICS_HASH_SECRET="$(tr -dc 'A-Z0-9' < /dev/urandom | head -c64)" # Perform replacements using sed with | as the delimiter sed -e "s|{{MASTER_SECRET}}|${MASTER_SECRET}|g" \ From 0f59f437afb4ed3d47dae8e7da311ff018e81b93 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Sun, 3 Dec 2023 23:27:16 -0400 Subject: [PATCH 47/54] Fix wizard grammar --- spk/ffsync/src/wizard/install_uifile.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spk/ffsync/src/wizard/install_uifile.sh b/spk/ffsync/src/wizard/install_uifile.sh index 61634d902cc..67c6b77d360 100644 --- a/spk/ffsync/src/wizard/install_uifile.sh +++ b/spk/ffsync/src/wizard/install_uifile.sh @@ -72,7 +72,7 @@ PAGE_FFSYNC_SETUP=$(/bin/cat<about:config. Change identity.sync.tokenserver.uri the following URL:", + "desc": "To configure your Firefox browser, go to about:config. Change identity.sync.tokenserver.uri to the following URL:", "subitems": [{ "key": "client_ffsync_public_url", "grow": true From f37ece259b292458fb0abe5fdbd3548ff535c23b Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Mon, 4 Dec 2023 05:40:10 -0400 Subject: [PATCH 48/54] Make clientUrl dynamic --- spk/ffsync/src/wizard/install_uifile.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spk/ffsync/src/wizard/install_uifile.sh b/spk/ffsync/src/wizard/install_uifile.sh index 67c6b77d360..dd71fe300a4 100644 --- a/spk/ffsync/src/wizard/install_uifile.sh +++ b/spk/ffsync/src/wizard/install_uifile.sh @@ -28,9 +28,9 @@ checkPublicUrl() var ipRegex = /^http:\/\/(\d{1,3}\.){3}\d{1,3}:8132$/; var domainRegex = /^http:\/\/((?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}):8132$/; if (ipRegex.test(publicUrl) || domainRegex.test(publicUrl)) { - clientUrl.disabled = false; - clientUrl.value = publicUrl + "/token/1.0/sync/1.5"; - clientUrl.disabled = true; + clientUrl.setReadOnly(false); + clientUrl.setValue(publicUrl + "/token/1.0/sync/1.5"); + clientUrl.setReadOnly(true); } else { return "Invalid URL format. Please provide a valid URL."; } From 0ac66017077ba78d7ac77fe9d5cc10311a7cf17f Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Mon, 4 Dec 2023 14:11:26 -0400 Subject: [PATCH 49/54] Refine wizards --- spk/ffsync/src/wizard/uninstall_uifile.sh | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/spk/ffsync/src/wizard/uninstall_uifile.sh b/spk/ffsync/src/wizard/uninstall_uifile.sh index caf3964e4ad..1e6060ff236 100644 --- a/spk/ffsync/src/wizard/uninstall_uifile.sh +++ b/spk/ffsync/src/wizard/uninstall_uifile.sh @@ -1,15 +1,5 @@ #!/bin/bash -# for backwards compatability -if [ $SYNOPKG_DSM_VERSION_MAJOR -lt 7 ]; then - if [ -z ${SYNOPKG_PKGDEST_VOL} ]; then - SYNOPKG_PKGDEST_VOL="/volume1" - fi - if [ -z ${SYNOPKG_PKGNAME} ]; then - SYNOPKG_PKGNAME="ffsync" - fi -fi - quote_json () { sed -e 's|\\|\\\\|g' -e 's|\"|\\\"|g' @@ -48,7 +38,6 @@ PAGE_FFSYNC_REMOVE=$(/bin/cat< Date: Mon, 4 Dec 2023 17:25:08 -0400 Subject: [PATCH 50/54] Include USB export paths --- spk/ffsync/src/wizard/uninstall_uifile.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spk/ffsync/src/wizard/uninstall_uifile.sh b/spk/ffsync/src/wizard/uninstall_uifile.sh index 1e6060ff236..4b7c45fcd19 100644 --- a/spk/ffsync/src/wizard/uninstall_uifile.sh +++ b/spk/ffsync/src/wizard/uninstall_uifile.sh @@ -41,7 +41,7 @@ PAGE_FFSYNC_REMOVE=$(/bin/cat< Date: Tue, 5 Dec 2023 20:54:32 -0400 Subject: [PATCH 51/54] Update package naming --- spk/ffsync/Makefile | 6 +++--- spk/ffsync/src/wizard/install_uifile.sh | 2 +- spk/ffsync/src/wizard/uninstall_uifile.sh | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index 1dc6b5f5c7f..8ae997db89d 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -14,9 +14,9 @@ REQUIRED_MIN_DSM = 6.0 SPK_DEPENDS = MariaDB10:$(PYTHON_PACKAGE) MAINTAINER = SynoCommunity -DESCRIPTION = Firefox Sync Server 1.5, used for Firefox 29 and later. You can use Firefox Sync Server to synchronize your bookmarks, passwords, settings, history, add-ons and tabs with Firefox on other computers. The service runs on port 8132. -DISPLAY_NAME = Firefox Sync Server 1.5 -CHANGELOG = "Inital Mozilla Sync Storage package." +DESCRIPTION = "An implementation of the Mozilla Sync-1.5 Server protocol used by the sync service in Firefox 29 and later. You can use Mozilla Sync Server to exchange browser data (bookmarks, history, open tabs, passwords, add-ons, and the like) between 'clients' in a manner that respects a user's security and privacy. The service runs on port 8132." +DISPLAY_NAME = Mozilla Sync Server +CHANGELOG = "Inital Mozilla Sync Server package." HOMEPAGE = https://mozilla-services.readthedocs.io/en/latest/howtos/run-sync-1.5.html LICENSE = MPL 2.0 diff --git a/spk/ffsync/src/wizard/install_uifile.sh b/spk/ffsync/src/wizard/install_uifile.sh index dd71fe300a4..9220b6cbfc5 100644 --- a/spk/ffsync/src/wizard/install_uifile.sh +++ b/spk/ffsync/src/wizard/install_uifile.sh @@ -43,7 +43,7 @@ EOF PAGE_FFSYNC_SETUP=$(/bin/cat< Date: Tue, 5 Dec 2023 21:49:04 -0400 Subject: [PATCH 52/54] Escape parentheses in description --- spk/ffsync/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index 8ae997db89d..042514b8dfa 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -14,7 +14,7 @@ REQUIRED_MIN_DSM = 6.0 SPK_DEPENDS = MariaDB10:$(PYTHON_PACKAGE) MAINTAINER = SynoCommunity -DESCRIPTION = "An implementation of the Mozilla Sync-1.5 Server protocol used by the sync service in Firefox 29 and later. You can use Mozilla Sync Server to exchange browser data (bookmarks, history, open tabs, passwords, add-ons, and the like) between 'clients' in a manner that respects a user's security and privacy. The service runs on port 8132." +DESCRIPTION = "An implementation of the Mozilla Sync-1.5 Server protocol used by the sync service in Firefox 29 and later. You can use Mozilla Sync Server to exchange browser data \(bookmarks, history, open tabs, passwords, add-ons, and the like\) between 'clients' in a manner that respects a user's security and privacy. The service runs on port 8132." DISPLAY_NAME = Mozilla Sync Server CHANGELOG = "Inital Mozilla Sync Server package." From 0c76c93455f9e288093e0d7d627a44462d6e1a48 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Tue, 5 Dec 2023 22:53:43 -0400 Subject: [PATCH 53/54] Remove quoting on description --- spk/ffsync/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spk/ffsync/Makefile b/spk/ffsync/Makefile index 042514b8dfa..0c20252e067 100644 --- a/spk/ffsync/Makefile +++ b/spk/ffsync/Makefile @@ -14,9 +14,9 @@ REQUIRED_MIN_DSM = 6.0 SPK_DEPENDS = MariaDB10:$(PYTHON_PACKAGE) MAINTAINER = SynoCommunity -DESCRIPTION = "An implementation of the Mozilla Sync-1.5 Server protocol used by the sync service in Firefox 29 and later. You can use Mozilla Sync Server to exchange browser data \(bookmarks, history, open tabs, passwords, add-ons, and the like\) between 'clients' in a manner that respects a user's security and privacy. The service runs on port 8132." +DESCRIPTION = An implementation of the Mozilla Sync-1.5 Server protocol used by the sync service in Firefox 29 and later. You can use Mozilla Sync Server to exchange browser data \(bookmarks, history, open tabs, passwords, add-ons, and the like\) between 'clients' in a manner that respects a user's security and privacy. The service runs on port 8132. DISPLAY_NAME = Mozilla Sync Server -CHANGELOG = "Inital Mozilla Sync Server package." +CHANGELOG = "Initial Mozilla Sync Server package." HOMEPAGE = https://mozilla-services.readthedocs.io/en/latest/howtos/run-sync-1.5.html LICENSE = MPL 2.0 From 17dffcd30e9cb2da2535e3cb05ad40c6a95e3ad9 Mon Sep 17 00:00:00 2001 From: mreid-tt <943378+mreid-tt@users.noreply.github.com> Date: Wed, 6 Dec 2023 07:07:29 -0400 Subject: [PATCH 54/54] Fix service setup formatting --- spk/ffsync/src/service-setup.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spk/ffsync/src/service-setup.sh b/spk/ffsync/src/service-setup.sh index 0524f91b897..ef5411cad90 100644 --- a/spk/ffsync/src/service-setup.sh +++ b/spk/ffsync/src/service-setup.sh @@ -1,3 +1,5 @@ + +# ffsync service setup PYTHON_DIR="/var/packages/python311/target/bin" PATH="${SYNOPKG_PKGDEST}/env/bin:${SYNOPKG_PKGDEST}/bin:${PYTHON_DIR}:${PATH}" @@ -130,7 +132,7 @@ EOF sed -e "s|{{MASTER_SECRET}}|${MASTER_SECRET}|g" \ -e "s|{{TCP_PORT}}|${SERVICE_PORT}|g" \ -e "s|{{SQL_USER}}|${DBUSER}|g" \ - -e "s|{{SQL_PASS}}|${DBPASS_ENC}|g" \ + -e "s|{{SQL_PASS}}|${DBPASS_ENC}|g" \ -e "s|{{DB_SERVER}}|${DBSERVER}|g" \ -e "s|{{METRICS_HASH_SECRET}}|${METRICS_HASH_SECRET}|g" \ -i "${CFG_FILE}"