Compare commits

..

2 Commits
v1.118.0 ... rm

Author SHA1 Message Date
Johannes Zellner
7480af6ebb Bump version 2024-05-14 19:30:23 +02:00
Johannes Zellner
7b29adda08 Fixup tests 2024-05-14 19:29:26 +02:00
10 changed files with 1716 additions and 1270 deletions

View File

@@ -1237,212 +1237,14 @@
[1.93.0] [1.93.0]
* Update Synapse to 1.107.0 * Update Synapse to 1.107.0
* [Full changelog](https://github.com/element-hq/synapse/releases/tag/v1.107.0) * [Full changelog](https://github.com/element-hq/synapse/releases/tag/v1.107.0)
* Add preliminary support for MSC3823: Account Suspension. (#17051)
[1.94.0] * Declare support for Matrix v1.10. Contributed by @clokep. (#17082)
* Update Synapse to 1.108.0 * Add support for MSC4115: membership metadata on events. (#17104, #17137)
* [Full changelog](https://github.com/element-hq/synapse/releases/tag/v1.108.0) * Fixed search feature of Element Android on homesevers using SQLite by returning search terms as search highlights. (#17000)
* Add a feature that allows clients to query the configured federation whitelist. Disabled by default. (#16848, #17199) * Fixes a bug introduced in v1.52.0 where the destination query parameter for the Destination Rooms Admin API failed to actually filter returned rooms. (#17077)
* Add the ability to allow numeric user IDs with a specific prefix when in the CAS flow. Contributed by Aurélien Grimpard. (#17098) * For MSC3266 room summaries, support queries at the recommended endpoint of /_matrix/client/unstable/im.nheko.summary/summary/{roomIdOrAlias}. The existing endpoint of /_matrix/client/unstable/im.nheko.summary/rooms/{roomIdOrAlias}/summary is deprecated. (#17078)
* Fix bug where push rules would be empty in /sync for some accounts. Introduced in v1.93.0. (#17142) * Apply user email & picture during OIDC registration if present & selected. (#17120)
* Add support for optional whitespace around the Federation API's Authorization header's parameter commas. (#17145) * Improve error message for cross signing reset with MSC3861 enabled. (#17121)
* Fix bug where disabling room publication prevented public rooms being created on workers. (#17177, #17184) * Fix a bug which meant that to-device messages received over federation could be dropped when the server was under load or networking problems caused problems between Synapse processes or the database. (#17127)
* Fix bug where StreamChangeCache would not respect configured cache factors. (#17152)
[1.95.0]
* Update Synapse to 1.109.0
* [Full changelog](https://github.com/element-hq/synapse/releases/tag/v1.109.0)
[1.96.0]
* Update Synapse to 1.110.0
* [Full changelog](https://github.com/element-hq/synapse/releases/tag/v1.110.0)
[1.97.0]
* Update Synapse to 1.111.0
* [Full changelog](https://github.com/element-hq/synapse/releases/tag/v1.111.0)
[1.97.1]
* Update Synapse to 1.111.1
* [Full changelog](https://github.com/element-hq/synapse/releases/tag/v1.111.1)
[1.97.2]
* Update Synapse to 1.112.0
* [Full changelog](https://github.com/element-hq/synapse/releases/tag/v1.112.0)
[1.97.3]
* Update Synapse to 1.113.0
* [Full changelog](https://github.com/element-hq/synapse/releases/tag/v1.113.0)
[1.97.4]
* Update Synapse to 1.114.0
* [Full changelog](https://github.com/element-hq/synapse/releases/tag/v1.114.0)
[1.97.5]
* Update Synapse to 1.115.0
* [Full changelog](https://github.com/element-hq/synapse/releases/tag/v1.115.0)
[1.97.6]
* Update Synapse to 1.116.0
* [Full changelog](https://github.com/element-hq/synapse/releases/tag/v1.116.0)
[1.98.0]
* Update Synapse to 1.118.0
* [Full changelog](https://github.com/element-hq/synapse/releases/tag/v1.118.0)
[1.98.1]
* Update S3 Storage Provider to 1.5.0
[1.99.0]
* Update synapse to 1.119.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.118.0)
* Support [MSC4151](https://github.com/matrix-org/matrix-spec-proposals/pull/4151)'s stable report room API. ([#​17374](https://github.com/element-hq/synapse/issues/17374))
* Add experimental support for [MSC4222](https://github.com/matrix-org/matrix-spec-proposals/pull/4222) (Adding `state_after` to sync v2). ([#​17888](https://github.com/element-hq/synapse/issues/17888))
* Fix bug with sliding sync where `$LAZY`-loading room members would not return `required_state` membership in incremental syncs. ([#​17809](https://github.com/element-hq/synapse/issues/17809))
* Check if user has membership in a room before tagging it. Contributed by Lama Alosaimi. ([#​17839](https://github.com/element-hq/synapse/issues/17839))
* Fix a bug in the admin redact endpoint where the background task would not run if a worker was specified in
* Fix bug where some presence and typing timeouts can expire early. ([#​17850](https://github.com/element-hq/synapse/issues/17850))
* Fix detection when the built Rust library was outdated when using source installations. ([#​17861](https://github.com/element-hq/synapse/issues/17861))
* Fix a long-standing bug in Synapse which could cause one-time keys to be issued in the incorrect order, causing message decryption failures. ([#​17903](https://github.com/element-hq/synapse/pull/17903))
* Fix experimental support for [MSC4222](https://github.com/matrix-org/matrix-spec-proposals/pull/4222) (Adding `state_after` to sync v2) where we would return the full state on incremental syncs when using lazy loaded members and there were no new events in the timeline. ([#​17915](https://github.com/element-hq/synapse/pull/17915))
* Remove support for python 3.8. ([#​17908](https://github.com/element-hq/synapse/issues/17908))
* Add a test for downloading and thumbnailing a CMYK JPEG. ([#​17786](https://github.com/element-hq/synapse/issues/17786))
* Refactor database calls to remove `Generator` usage. ([#​17813](https://github.com/element-hq/synapse/issues/17813), [#​17814](https://github.com/element-hq/synapse/issues/17814), [#​17815](https://github.com/element-hq/synapse/issues/17815), [#​17816](https://github.com/element-hq/synapse/issues/17816), [#​17817](https://github.com/element-hq/synapse/issues/17817), [#​17818](https://github.com/element-hq/synapse/issues/17818), [#​17890](https://github.com/element-hq/synapse/issues/17890))
* Include the destination in the error of 'Destination mismatch' on federation requests. ([#​17830](https://github.com/element-hq/synapse/issues/17830))
* The nix flake inside the repository no longer tracks nixpkgs/master to not catch the latest bugs from a MR merged 5 minutes ago. ([#​17852](https://github.com/element-hq/synapse/issues/17852))
* Minor speed-up of sliding sync by computing extensions results in parallel. ([#​17884](https://github.com/element-hq/synapse/issues/17884))
* Bump the default Python version in the Synapse Dockerfile from 3.11 -> 3.12. ([#​17887](https://github.com/element-hq/synapse/issues/17887))
* Remove usage of internal header encoding API. ([#​17894](https://github.com/element-hq/synapse/issues/17894))
* Use unique name for each os.arch variant when uploading Wheel artifacts. ([#​17905](https://github.com/element-hq/synapse/issues/17905))
* Fix tests to run with latest Twisted. ([#​17906](https://github.com/element-hq/synapse/pull/17906), [#​17907](https://github.com/element-hq/synapse/pull/17907), [#​17911](https://github.com/element-hq/synapse/pull/17911))
* Update version constraint to allow the latest poetry-core 1.9.1. ([#​17902](https://github.com/element-hq/synapse/pull/17902))
* Update the portdb CI to use Python 3.13 and Postgres 17 as latest dependencies. ([#​17909](https://github.com/element-hq/synapse/pull/17909))
* Add an index to `current_state_delta_stream` table. ([#​17912](https://github.com/element-hq/synapse/issues/17912))
* Fix building and attaching release artifacts during the release process. ([#​17921](https://github.com/element-hq/synapse/issues/17921))
[1.100.0]
* Update synapse to 1.120.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.118.0)
* Fix a bug introduced in Synapse v1.120rc1 which would cause the newly-introduced `delete_old_otks` job to fail in worker-mode deployments. ([#​17960](https://github.com/element-hq/synapse/issues/17960))
[1.100.1]
* Update synapse to 1.120.2
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.118.0)
[1.101.0]
* Update synapse to 1.121.1
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.121.0)
* Support for MSC4190: device management for Application Services. (#17705)
* Update MSC4186 Sliding Sync to include invite, ban, kick, targets when $LAZY-loading room members. (#17947)
* Use stable M_USER_LOCKED error code for locked accounts, as per Matrix 1.12. (#17965)
* MSC4076: Add disable_badge_count to pusher configuration. (#17975)
[1.101.1]
* CLOUDRON_OIDC_PROVIDER_NAME implemented
[1.102.0]
* Update synapse to 1.122.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.122.0)
[1.103.0]
* Update synapse to 1.123.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.123.0)
[1.104.0]
* Update synapse to 1.124.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.124.0)
[1.105.0]
* Update synapse to 1.125.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.125.0)
* Add functionality to be able to use multiple values in SSO feature attribute_requirements. (#17949)
* Add experimental config options admin_token_path and client_secret_path for MSC3861. (#18004)
* Add get_current_time_msec() method to the module API for sound time comparisons with Synapse. (#18144)
* Update the response when a client attempts to add an invalid email address to the user's account from a 500, to a 400 with error text. (#18125)
* Fix user directory search when using a legacy module with a check_username_for_spam callback. Broke in v1.122.0. (#18135)
[1.106.0]
* Update synapse to 1.126.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.126.0)
* Define ratelimit configuration for delayed event management. (#18019)
* Add form_secret_path config option. (#18090)
* Add the --no-secrets-in-config command line option. (#18092)
* Add background job to clear unreferenced state groups. (#18154)
* Add support for specifying/overriding id_token_signing_alg_values_supported for an OpenID identity provider. (#18177)
* Add worker_replication_secret_path config option. (#18191)
* Add support for specifying/overriding redirect_uri in the authorization and token requests against an OpenID identity provider. (#18197)
[1.107.0]
* Update base image to 5.0.0
[1.108.0]
* Update synapse to 1.127.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.127.0)
* Update MSC4140 implementation to no longer cancel a user's own delayed state events with an event type & state key that match a more recent state event sent by that user. (#17810)
* Fixed a minor typo in the Synapse documentation. Contributed by @karuto12. (#18224)
* Remove undocumented SYNAPSE_USE_FROZEN_DICTS environment variable. (#18123)
* Fix detection of workflow failures in the release script. (#18211)
* Add caching support to media endpoints. (#18235)
[1.108.1]
* Update synapse to 1.127.1
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.127.1)
* Fix CVE-2025-30355 / GHSA-v56r-hwv5-mxg6. High severity vulnerability affecting federation. The vulnerability has been exploited in the wild.
[1.109.0]
* Update synapse to 1.128.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.128.0)
* Add an access token introspection cache to make Matrix Authentication Service integration (MSC3861) more efficient. (#18231)
* Add background job to clear unreferenced state groups. (#18254)
* Hashes of media files are now tracked by Synapse. Media quarantines will now apply to all files with the same hash. (#18277, #18302, #18296)
[1.110.0]
* Update synapse to 1.129.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.129.0)
[1.111.0]
* Update synapse to 1.130.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.130.0)
* Fix startup being blocked on creating a new index that was introduced in v1.130.0rc1. ([#​18439](https://github.com/element-hq/synapse/issues/18439))
* Fix the ordering of local messages in rooms that were affected by [GHSA-v56r-hwv5-mxg6](https://github.com/advisories/GHSA-v56r-hwv5-mxg6). ([#​18447](https://github.com/element-hq/synapse/issues/18447))
[1.112.0]
* Update synapse to 1.131.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.131.0)
[1.113.0]
* Update synapse to 1.132.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.132.0)
[1.114.0]
* Update synapse to 1.133.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.133.0)
* Pre-built wheels are now built using the manylinux\_2\_28 base, which is expected to be compatible with distros using glibc 2.28 or later, including:
* Previously, wheels were built using the manylinux2014 base, which was expected to be compatible with distros using glibc 2.17 or later.
* Bump `cibuildwheel` to 3.0.0 to fix the `manylinux` wheel builds. ([#​18615](https://github.com/element-hq/synapse/issues/18615))
[1.115.0]
* Update synapse to 1.134.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.134.0)
[1.116.0]
* Update synapse to 1.135.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.135.0)
[1.116.1]
* Update synapse to 1.135.2
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.135.2)
* Fix invalidation of storage cache that was broken in 1.135.0. ([#​18786](https://github.com/element-hq/synapse/issues/18786))
* Add a parameter to `upgrade_rooms(..)` to allow auto join local users. ([#​82](https://github.com/element-hq/synapse/issues/82))
* Speed up upgrading a room with large numbers of banned users. ([#​18574](https://github.com/element-hq/synapse/issues/18574))
[1.117.0]
* Update synapse to 1.136.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.136.0)
* Fix bug introduced in 1.135.2 and 1.136.0rc2 where the [Make Room Admin API](https://element-hq.github.io/synapse/latest/admin_api/rooms.html#make-room-admin-api) would not treat a room v12's creator power level as the highest in room. ([#​18805](https://github.com/element-hq/synapse/issues/18805))
[1.118.0]
* Update synapse to 1.137.0
* [Full Changelog](https://github.com/element-hq/synapse/releases/tag/v1.137.0)
* Fix a bug which could corrupt auth chains making it impossible to perform state resolution. (#18746)
* Fix error message in register_new_matrix_user utility script for empty registration_shared_secret. (#18780)
* Allow enabling MSC4108 when the stable Matrix Authentication Service integration is enabled. (#18832)
* Include IPv6 networks in denied-peer-ips of coturn setup. Contributed by @litetex. (#18781)

View File

@@ -5,57 +5,33 @@
"description": "file://DESCRIPTION.md", "description": "file://DESCRIPTION.md",
"changelog": "file://CHANGELOG.md", "changelog": "file://CHANGELOG.md",
"tagline": "Secure & decentralized communication", "tagline": "Secure & decentralized communication",
"version": "1.118.0", "version": "1.93.0",
"upstreamVersion": "1.137.0", "upstreamVersion": "1.107.0",
"healthCheckPath": "/", "healthCheckPath": "/",
"httpPort": 8008, "httpPort": 8008,
"memoryLimit": 536870912, "memoryLimit": 536870912,
"addons": { "addons": {
"localstorage": {}, "localstorage": {},
"oidc": { "oidc": { "loginRedirectUri": "/_synapse/client/oidc/callback" },
"loginRedirectUri": "/_synapse/client/oidc/callback"
},
"postgresql": {}, "postgresql": {},
"sendmail": { "sendmail": { "supportsDisplayName": true },
"supportsDisplayName": true "turn": { "optional": true }
},
"turn": {
"optional": true
}
}, },
"manifestVersion": 2, "manifestVersion": 2,
"website": "https://matrix.org", "website": "https://matrix.org",
"contactEmail": "support@cloudron.io", "contactEmail": "support@cloudron.io",
"icon": "file://logo.png", "icon": "file://logo.png",
"tags": [ "tags": [
"im", "im", "collaboration", "voip", "videochat", "chat", "slack", "zulip", "federated"
"collaboration",
"voip",
"videochat",
"chat",
"slack",
"zulip",
"federated",
"element",
"riot"
], ],
"mediaLinks": [ "mediaLinks": [
"https://screenshots.cloudron.io/org.matrix.synapse/1.png", "https://screenshots.cloudron.io/org.matrix.synapse/1.png",
"https://screenshots.cloudron.io/org.matrix.synapse/2.png", "https://screenshots.cloudron.io/org.matrix.synapse/2.png",
"https://screenshots.cloudron.io/org.matrix.synapse/3.png" "https://screenshots.cloudron.io/org.matrix.synapse/3.png"
], ],
"checklist": {
"configure-federation": {
"message": "For federation to work, the delegation URI `https://$CLOUDRON-APP-DOMAIN/.well-known/matrix/server` must be configured. See the [docs](https://docs.cloudron.io/apps/synapse/#post-installation) on how to do this."
},
"registration-enabled-without-verification": {
"message": "Registration is enabled but verification is disabled. See [docs](https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html?highlight=registration_require#enable_registration) for more information",
"sso": false
}
},
"postInstallMessage": "file://POSTINSTALL.md", "postInstallMessage": "file://POSTINSTALL.md",
"minBoxVersion": "8.2.0", "minBoxVersion": "7.5.1",
"forumUrl": "https://forum.cloudron.io/category/50/matrix-synapse-riot", "forumUrl": "https://forum.cloudron.io/category/50/matrix-synapse-riot",
"documentationUrl": "https://docs.cloudron.io/packages/synapse/", "documentationUrl": "https://docs.cloudron.io/apps/synapse/",
"optionalSso": true "optionalSso": true
} }

View File

@@ -1,27 +1,31 @@
FROM cloudron/base:5.0.0@sha256:04fd70dbd8ad6149c19de39e35718e024417c3e01dc9c6637eaf4a41ec4e596c FROM cloudron/base:4.2.0@sha256:46da2fffb36353ef714f97ae8e962bd2c212ca091108d768ba473078319a47f4
RUN mkdir -p /app/pkg RUN mkdir -p /app/pkg
WORKDIR /app/code WORKDIR /app/code
# https://github.com/element-hq/synapse/blob/master/docs/setup/installation.md?plain=1#L202 # https://pythonspeed.com/articles/activate-virtualenv-dockerfile/
RUN python3 -m venv /app/code/env RUN virtualenv -p python3 /app/code/env
ENV VIRTUAL_ENV=/app/code/env
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
# renovate: datasource=github-releases depName=element-hq/synapse versioning=semver extractVersion=^v(?<version>.+)$ ARG VERSION=1.107.0
ARG SYNAPSE_VERSION=1.137.0
# renovate: datasource=github-releases depName=matrix-org/synapse-s3-storage-provider versioning=semver extractVersion=^v(?<version>.+)$ # https://github.com/matrix-org/synapse-s3-storage-provider
ARG S3PROVIDER_VERSION=1.5.0 ARG STORAGE_PROVIDER_VERSION=1beb6af95e1f5caedb8e6e7e1cc176cdb2106d37
# Synapse (https://github.com/matrix-org/synapse/blob/master/INSTALL.md) # Synapse (https://github.com/matrix-org/synapse/blob/master/INSTALL.md)
# lxml - required for previews # lxml - required for previews
RUN source /app/code/env/bin/activate && \ RUN pip install --upgrade pip && \
pip3 install --no-cache-dir matrix-synapse==v${SYNAPSE_VERSION} psycopg2-binary python-ldap matrix-synapse-ldap3 lxml publicsuffix2 git+https://github.com/matrix-org/synapse-s3-storage-provider.git@v${S3PROVIDER_VERSION} matrix-synapse[oidc] pip install --upgrade setuptools && \
pip install matrix-synapse==v${VERSION} psycopg2-binary python-ldap matrix-synapse-ldap3 lxml publicsuffix2 git+https://github.com/matrix-org/synapse-s3-storage-provider.git@${STORAGE_PROVIDER_VERSION} matrix-synapse[oidc]
# Updated suffix list # Updated suffix list
RUN curl -L https://publicsuffix.org/list/public_suffix_list.dat -o /app/code/env/lib/python3.12/site-packages/publicsuffix2/public_suffix_list.dat RUN curl -L https://publicsuffix.org/list/public_suffix_list.dat -o /app/code/env/lib/python3.10/site-packages/publicsuffix2/public_suffix_list.dat
RUN ln -sf /app/data/index.html /app/code/env/lib/python3.12/site-packages/synapse/static/index.html RUN ln -sf /app/data/index.html /app/code/env/lib/python3.10/site-packages/synapse/static/index.html
RUN chown -R cloudron.cloudron /app/code
ADD index.html homeserver.yaml.template start.sh /app/pkg/ ADD index.html homeserver.yaml.template start.sh /app/pkg/

View File

@@ -1,2 +1,6 @@
Account ids are created with the username and the second level domain under which the Account ids are created with the username and the second level domain under which the
app is installed e.g. `@$CLOUDRON-USERNAME:$CLOUDRON-APP-DOMAIN`. app is installed e.g. `@$CLOUDRON-USERNAME:$CLOUDRON-APP-DOMAIN`.
For federation to work, the delegation URI `https://$CLOUDRON-APP-DOMAIN/.well-known/matrix/server`
must be configured. See the [docs](https://docs.cloudron.io/apps/synapse/#post-installation) on how to do this.

View File

@@ -1,4 +1,4 @@
# https://github.com/element-hq/synapse/blob/master/docs/sample_config.yaml # https://github.com/matrix-org/synapse/blob/master/docs/sample_config.yaml
# if you change this, change the auto_join_rooms below as well # if you change this, change the auto_join_rooms below as well
server_name: "example.com" server_name: "example.com"
@@ -13,6 +13,7 @@ listeners:
type: http type: http
x_forwarded: true x_forwarded: true
bind_addresses: ['0.0.0.0'] bind_addresses: ['0.0.0.0']
resources: resources:
- names: [client,federation] - names: [client,federation]
compress: false compress: false
@@ -20,6 +21,7 @@ listeners:
database: database:
name: "psycopg2" name: "psycopg2"
args: args:
# Path to the database
user: ${POSTGRESQL_USERNAME} user: ${POSTGRESQL_USERNAME}
password: ${POSTGRESQL_PASSWORD} password: ${POSTGRESQL_PASSWORD}
database: ${POSTGRESQL_DATABASE} database: ${POSTGRESQL_DATABASE}
@@ -27,17 +29,6 @@ database:
cp_min: 5 cp_min: 5
cp_max: 10 cp_max: 10
log_config: "/app/data/configs/log.config"
media_store_path: "/app/data/data/media_store"
registration_shared_secret: "some_shared_secret"
report_stats: false
macaroon_secret_key: "some_macaroon_secret"
form_secret: "some_form_secret"
signing_key_path: "/app/data/configs/signing.key"
trusted_key_servers:
- server_name: "matrix.org"
## Cloudron packaging
email: email:
smtp_host: mail.server smtp_host: mail.server
smtp_port: 587 smtp_port: 587
@@ -49,37 +40,74 @@ email:
enable_notifs: true enable_notifs: true
notif_for_new_users: true notif_for_new_users: true
password_providers:
- module: "synapse.util.ldap_auth_provider.LdapAuthProvider"
config:
enabled: true
uri: "ldap://ldap.example.com:389"
start_tls: true
base: "ou=users,dc=example,dc=com"
attributes:
uid: "username"
mail: "mail"
name: "username"
bind_dn: "ou=users,dc=cloudron"
bind_password: "password"
filter: "(objectClass=posixAccount)"
# turn # turn
turn_uris: [] turn_uris: []
turn_shared_secret: "sharedsecret" turn_shared_secret: "sharedsecret"
turn_allow_guests: true turn_allow_guests: true
# sso (https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#single-sign-on-integration) federation_ip_range_blacklist:
enable_registration: false - '127.0.0.0/8'
# without this, registration requires one of email/captcha/token verification - '10.0.0.0/8'
enable_registration_without_verification: true - '172.16.0.0/12'
- '192.168.0.0/16'
- '100.64.0.0/10'
- '169.254.0.0/16'
- '::1/128'
- 'fe80::/64'
- 'fc00::/7'
oidc_providers: enable_registration: false
- idp_id: cloudron enable_registration_without_verification: true
idp_name: "CLOUDRON_OIDC_PROVIDER_NAME" registration_shared_secret: "somesecret"
issuer: "CLOUDRON_OIDC_ISSUER" allow_guest_access: false
client_id: "CLOUDRON_OIDC_CLIENT_ID"
client_secret: "CLOUDRON_OIDC_CLIENT_SECRET" enable_group_creation: true
scopes: ["openid", "profile", "email"]
authorization_endpoint: "CLOUDRON_OIDC_AUTH_ENDPOINT" report_stats: False
token_endpoint: "CLOUDRON_OIDC_TOKEN_ENDPOINT"
userinfo_endpoint: "CLOUDRON_OIDC_AUTH_ENDPOINT" signing_key_path: "/app/data/configs/signing.key"
allow_existing_users: true
enable_registration: true url_preview_enabled: true
backchannel_logout_enabled: false url_preview_ip_range_blacklist:
user_mapping_provider: - '127.0.0.0/8'
config: - '10.0.0.0/8'
localpart_template: "{{ user.sub }}" - '172.16.0.0/12'
display_name_template: "{{ user.name }}" - '192.168.0.0/16'
email_template: "{{ user.email }}" - '100.64.0.0/10'
- '169.254.0.0/16'
- '::1/128'
- 'fe80::/64'
- 'fc00::/7'
media_store_path: "/app/data/data/media_store"
max_upload_size: 200M
max_image_pixels: "32M"
dynamic_thumbnails: false
autocreate_auto_join_rooms: true
auto_join_rooms:
- "#discuss:example.com"
trusted_key_servers:
- server_name: "matrix.org"
suppress_key_server_warning: true
password_config: password_config:
enabled: false enabled: true
localdb_enabled: false localdb_enabled: false
pepper: "some_pepper_secret"

View File

@@ -1,4 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["local>devops/renovator//default.renovate.json5"]
}

View File

@@ -4,8 +4,6 @@ set -eu
mkdir -p /app/data/data /app/data/configs /run/synapse mkdir -p /app/data/data /app/data/configs /run/synapse
source /app/code/env/bin/activate
if [[ ! -f /app/data/configs/homeserver.yaml ]]; then if [[ ! -f /app/data/configs/homeserver.yaml ]]; then
echo "==> Detected first run" echo "==> Detected first run"
@@ -33,14 +31,14 @@ if [[ ! -f /app/data/configs/homeserver.yaml ]]; then
yq eval -i ".server_name=\"${server_name}\"" /app/data/configs/homeserver.yaml yq eval -i ".server_name=\"${server_name}\"" /app/data/configs/homeserver.yaml
yq eval -i ".registration_shared_secret=\"$(pwgen -1s 64)\"" /app/data/configs/homeserver.yaml yq eval -i ".registration_shared_secret=\"$(pwgen -1s 64)\"" /app/data/configs/homeserver.yaml
yq eval -i ".macaroon_secret_key=\"$(pwgen -1s 64)\"" /app/data/configs/homeserver.yaml
yq eval -i ".form_secret=\"$(pwgen -1s 64)\"" /app/data/configs/homeserver.yaml yq eval -i ".auto_join_rooms=[]" /app/data/configs/homeserver.yaml
yq eval -i ".auto_join_rooms[0]=\"#discuss:${server_name}\"" /app/data/configs/homeserver.yaml
if [[ -z "${CLOUDRON_OIDC_ISSUER:-}" ]]; then if [[ -z "${CLOUDRON_OIDC_ISSUER:-}" ]]; then
yq eval -i ".enable_registration=true" /app/data/configs/homeserver.yaml yq eval -i ".enable_registration=true" /app/data/configs/homeserver.yaml
yq eval -i ".password_config.enabled=true" /app/data/configs/homeserver.yaml # just setting enabled to false is not enough. see https://github.com/matrix-org/matrix-synapse-ldap3/issues/123
yq eval -i ".password_config.localdb_enabled=true" /app/data/configs/homeserver.yaml yq eval -i "del(.password_providers)" /app/data/configs/homeserver.yaml
yq eval -i "del(.oidc_providers)" /app/data/configs/homeserver.yaml
fi fi
yq eval -i ".password_config.pepper=\"$(pwgen -1s 12)\"" /app/data/configs/homeserver.yaml # always set this so that users can enable password login if needed yq eval -i ".password_config.pepper=\"$(pwgen -1s 12)\"" /app/data/configs/homeserver.yaml # always set this so that users can enable password login if needed
fi fi
@@ -69,9 +67,10 @@ yq eval -i ".email.notif_from=\"${CLOUDRON_MAIL_FROM_DISPLAY_NAME:-Matrix} <${CL
# oidc # oidc
if [[ -n "${CLOUDRON_OIDC_ISSUER:-}" ]]; then if [[ -n "${CLOUDRON_OIDC_ISSUER:-}" ]]; then
yq eval -i "del(.password_providers)" /app/data/configs/homeserver.yaml # remove old ldap config
echo " ==> Configuring OIDC auth" echo " ==> Configuring OIDC auth"
yq eval -i ".oidc_providers[0].idp_id=\"cloudron\"" /app/data/configs/homeserver.yaml yq eval -i ".oidc_providers[0].idp_id=\"cloudron\"" /app/data/configs/homeserver.yaml
yq eval -i ".oidc_providers[0].idp_name=\"${CLOUDRON_OIDC_PROVIDER_NAME:-Cloudron}\"" /app/data/configs/homeserver.yaml yq eval -i ".oidc_providers[0].idp_name=\"Cloudron\"" /app/data/configs/homeserver.yaml
yq eval -i ".oidc_providers[0].issuer=\"${CLOUDRON_OIDC_ISSUER}\"" /app/data/configs/homeserver.yaml yq eval -i ".oidc_providers[0].issuer=\"${CLOUDRON_OIDC_ISSUER}\"" /app/data/configs/homeserver.yaml
yq eval -i ".oidc_providers[0].client_id=\"${CLOUDRON_OIDC_CLIENT_ID}\"" /app/data/configs/homeserver.yaml yq eval -i ".oidc_providers[0].client_id=\"${CLOUDRON_OIDC_CLIENT_ID}\"" /app/data/configs/homeserver.yaml
yq eval -i ".oidc_providers[0].client_secret=\"${CLOUDRON_OIDC_CLIENT_SECRET}\"" /app/data/configs/homeserver.yaml yq eval -i ".oidc_providers[0].client_secret=\"${CLOUDRON_OIDC_CLIENT_SECRET}\"" /app/data/configs/homeserver.yaml
@@ -85,9 +84,10 @@ if [[ -n "${CLOUDRON_OIDC_ISSUER:-}" ]]; then
yq eval -i ".oidc_providers[0].skip_verification=true" /app/data/configs/homeserver.yaml yq eval -i ".oidc_providers[0].skip_verification=true" /app/data/configs/homeserver.yaml
yq eval -i ".oidc_providers[0].user_mapping_provider.config.localpart_template=\"{{ user.sub }}\"" /app/data/configs/homeserver.yaml yq eval -i ".oidc_providers[0].user_mapping_provider.config.localpart_template=\"{{ user.sub }}\"" /app/data/configs/homeserver.yaml
yq eval -i ".oidc_providers[0].user_mapping_provider.config.display_name_template=\"{{ user.name }}\"" /app/data/configs/homeserver.yaml yq eval -i ".oidc_providers[0].user_mapping_provider.config.display_name_template=\"{{ user.name }}\"" /app/data/configs/homeserver.yaml
yq eval -i ".oidc_providers[0].user_mapping_provider.config.email_template=\"{{ user.email }}\"" /app/data/configs/homeserver.yaml
else else
yq eval -i ".password_config.localdb_enabled=true" /app/data/configs/homeserver.yaml yq eval -i ".password_config.localdb_enabled=true" /app/data/configs/homeserver.yaml
# just setting enabled to false is not enough. see https://github.com/matrix-org/matrix-synapse-ldap3/issues/123
yq eval -i "del(.password_providers)" /app/data/configs/homeserver.yaml
fi fi
# turn (https://github.com/matrix-org/synapse/blob/master/docs/turn-howto.md#synapse-setup) # turn (https://github.com/matrix-org/synapse/blob/master/docs/turn-howto.md#synapse-setup)
@@ -100,7 +100,7 @@ fi
# fix permissions # fix permissions
echo "==> Fixing permissions" echo "==> Fixing permissions"
chown -R cloudron:cloudron /app/data /run/synapse chown -R cloudron.cloudron /app/data /run/synapse
echo "==> Starting synapse" echo "==> Starting synapse"
exec gosu cloudron:cloudron python3 -m synapse.app.homeserver --config-path /app/data/configs/homeserver.yaml -n gosu cloudron:cloudron python3 -m synapse.app.homeserver --config-path /app/data/configs/homeserver.yaml -n

2324
test/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,9 +9,9 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"chromedriver": "^139.0.2", "chromedriver": "^124.0.3",
"expect.js": "^0.3.1", "expect.js": "^0.3.1",
"mocha": "^11.7.1", "mocha": "^10.4.0",
"selenium-webdriver": "^4.35.0" "selenium-webdriver": "^4.20.0"
} }
} }

View File

@@ -1,7 +1,11 @@
#!/usr/bin/env node #!/usr/bin/env node
/* jshint esversion: 8 */ /* jshint esversion: 8 */
/* global it, xit, describe, before, after, afterEach */ /* global it:false */
/* global xit:false */
/* global describe:false */
/* global before:false */
/* global after:false */
'use strict'; 'use strict';
@@ -9,11 +13,11 @@ require('chromedriver');
const execSync = require('child_process').execSync, const execSync = require('child_process').execSync,
expect = require('expect.js'), expect = require('expect.js'),
fs = require('fs'),
path = require('path'), path = require('path'),
{ Builder, By, Key, until } = require('selenium-webdriver'), { Builder, By, Key, until } = require('selenium-webdriver'),
{ Options } = require('selenium-webdriver/chrome'); { Options } = require('selenium-webdriver/chrome');
if (!process.env.USERNAME || !process.env.PASSWORD) { if (!process.env.USERNAME || !process.env.PASSWORD) {
console.log('USERNAME and PASSWORD env vars need to be set'); console.log('USERNAME and PASSWORD env vars need to be set');
process.exit(1); process.exit(1);
@@ -23,7 +27,7 @@ describe('Application life cycle test', function () {
this.timeout(0); this.timeout(0);
const ELEMENT_LOCATION = 'element-test'; const ELEMENT_LOCATION = 'element-test';
const LOCATION = process.env.LOCATION || 'test'; const LOCATION = 'test';
const TEST_TIMEOUT = parseInt(process.env.TIMEOUT, 10) || 10000; const TEST_TIMEOUT = parseInt(process.env.TIMEOUT, 10) || 10000;
const EXEC_ARGS = { cwd: path.resolve(__dirname, '..'), stdio: 'inherit' }; const EXEC_ARGS = { cwd: path.resolve(__dirname, '..'), stdio: 'inherit' };
const USERNAME = process.env.USERNAME; const USERNAME = process.env.USERNAME;
@@ -32,40 +36,22 @@ describe('Application life cycle test', function () {
const ROOM_NAME = 'Test room ' + ROOM_ID; const ROOM_NAME = 'Test room ' + ROOM_ID;
const MSG_TEXT = 'Test message '; const MSG_TEXT = 'Test message ';
let browser, app, elementApp; let browser, app;
let athenticated_by_oidc = false;
before(function () { before(function () {
const chromeOptions = new Options().windowSize({ width: 1280, height: 1024 }); const options = new Options().windowSize({ width: 1280, height: 1024 });
if (process.env.CI) chromeOptions.addArguments('no-sandbox', 'disable-dev-shm-usage', 'headless'); if (process.env.HEADLESS) options.addArguments('headless');
browser = new Builder().forBrowser('chrome').setChromeOptions(chromeOptions).build();
if (!fs.existsSync('./screenshots')) fs.mkdirSync('./screenshots');
if (process.env.CI) execSync(`cloudron uninstall --app ${ELEMENT_LOCATION} || true`, EXEC_ARGS); browser = new Builder().forBrowser('chrome').setChromeOptions(options).build();
}); });
after(function () { after(function () {
browser.quit(); browser.quit();
}); });
afterEach(async function () { function sleep(millis) {
if (!process.env.CI || !app) return; return new Promise(resolve => setTimeout(resolve, millis));
const currentUrl = await browser.getCurrentUrl();
if (!currentUrl.includes(app.domain)) return;
expect(this.currentTest.title).to.be.a('string');
const screenshotData = await browser.takeScreenshot();
fs.writeFileSync(`./screenshots/${new Date().getTime()}-${this.currentTest.title.replaceAll(' ', '_')}.png`, screenshotData, 'base64');
});
async function clearCache() {
await browser.manage().deleteAllCookies();
await browser.quit();
browser = null;
const chromeOptions = new Options().windowSize({ width: 1280, height: 1024 });
if (process.env.CI) chromeOptions.addArguments('no-sandbox', 'disable-dev-shm-usage', 'headless');
chromeOptions.addArguments(`--user-data-dir=${await fs.promises.mkdtemp('/tmp/test-')}`); // --profile-directory=Default
browser = new Builder().forBrowser('chrome').setChromeOptions(chromeOptions).build();
} }
async function waitForElement(elem) { async function waitForElement(elem) {
@@ -81,8 +67,8 @@ describe('Application life cycle test', function () {
function getElementAppInfo() { function getElementAppInfo() {
const inspect = JSON.parse(execSync('cloudron inspect')); const inspect = JSON.parse(execSync('cloudron inspect'));
elementApp = inspect.apps.filter(function (a) { return a.location.indexOf(ELEMENT_LOCATION) === 0; })[0]; app = inspect.apps.filter(function (a) { return a.location.indexOf(ELEMENT_LOCATION) === 0; })[0];
expect(elementApp).to.be.an('object'); expect(app).to.be.an('object');
} }
function getMessage() { function getMessage() {
@@ -91,11 +77,10 @@ describe('Application life cycle test', function () {
async function updateSynapseConfig() { async function updateSynapseConfig() {
console.log(`Setting Synapse Matrix server location to "https://${app.fqdn}"`); console.log(`Setting Synapse Matrix server location to "https://${app.fqdn}"`);
execSync(`cloudron exec --app ${ELEMENT_LOCATION} -- bash -c "jq '.default_server_config[\\"m.homeserver\\"].base_url = \\"https://${app.fqdn}\\"' /app/data/config.json | sponge /app/data/config.json"`); execSync(`cloudron exec --app ${ELEMENT_LOCATION} -- bash -c "jq '.default_server_config[\\"m.homeserver\\"].base_url = \\"https://${app.fqdn}\\"' /app/data/config.json | sponge /app/data/config.json"`);
execSync(`cloudron restart --app ${ELEMENT_LOCATION}`); execSync(`cloudron restart --app ${ELEMENT_LOCATION}`);
// wait when all services are up and running // wait when all services are up and running
await browser.sleep(15000); await sleep(15000);
} }
async function checkLandingPage() { async function checkLandingPage() {
@@ -104,87 +89,49 @@ describe('Application life cycle test', function () {
} }
async function registerUser() { async function registerUser() {
await browser.get(`https://${elementApp.fqdn}/#/register`); await browser.get(`https://${app.fqdn}/#/register`);
await waitForElement(By.xpath('//input[@label="Username"]')); await waitForElement(By.xpath('//input[@label="Username"]'));
await browser.findElement(By.xpath('//input[@label="Username"]')).sendKeys(USERNAME); await browser.findElement(By.xpath('//input[@label="Username"]')).sendKeys(USERNAME);
await browser.sleep(2000);
await browser.findElement(By.xpath('//input[@label="Password"]')).sendKeys(PASSWORD); await browser.findElement(By.xpath('//input[@label="Password"]')).sendKeys(PASSWORD);
await browser.sleep(2000);
await browser.findElement(By.xpath('//input[@label="Confirm password"]')).sendKeys(PASSWORD); await browser.findElement(By.xpath('//input[@label="Confirm password"]')).sendKeys(PASSWORD);
await browser.sleep(2000);
await browser.findElement(By.xpath('//input[@value="Register"]')).click(); await browser.findElement(By.xpath('//input[@value="Register"]')).click();
await browser.sleep(2000);
await waitForElement(By.xpath('//h1[text()="You\'re in"] | //h1[contains(., "Welcome")]')); await waitForElement(By.xpath('//h1[text()="You\'re in"]'));
if (await browser.findElements(By.xpath('//div[@role="button" and text()="Skip"]')).then(found => !!found.length)) { await browser.sleep(2000);
await browser.findElement(By.xpath('//div[@role="button" and text()="Skip"]')).click(); await browser.findElement(By.xpath('//div[@role="button" and text()="Skip"]')).click();
} await browser.sleep(2000);
await waitForElement(By.xpath(`//h1[contains(., "Welcome")]`)); await waitForElement(By.xpath(`//h1[contains(., "Welcome")]`));
} }
async function loginOIDC(username, password, alreadyAuthenticated, proceedWithReset) { async function loginOIDC(username, password) {
await browser.get(`https://${elementApp.fqdn}/#/login`); browser.manage().deleteAllCookies();
await browser.get(`https://${app.fqdn}/#/login`);
await browser.sleep(6000);
await waitForElement(By.xpath('//div[@role="button" and contains(., "Continue with Cloudron")]'));
await browser.findElement(By.xpath('//div[@role="button" and contains(., "Continue with Cloudron")]')).click();
await browser.sleep(2000); await browser.sleep(2000);
await waitForElement(By.css('.mx_Dropdown_arrow')); if (!athenticated_by_oidc) {
await browser.findElement(By.css('.mx_Dropdown_arrow')).click(); await waitForElement(By.xpath('//input[@name="username"]'));
await waitForElement(By.id('mx_LanguageDropdown__en')); await browser.findElement(By.xpath('//input[@name="username"]')).sendKeys(username);
await browser.findElement(By.id('mx_LanguageDropdown__en')).click(); await browser.findElement(By.xpath('//input[@name="password"]')).sendKeys(password);
await browser.sleep(3000); await browser.sleep(2000);
await waitForElement(By.xpath('//div[@role="button" and contains(., "Continue with")]'));
await browser.findElement(By.xpath('//div[@role="button" and contains(., "Continue with")]')).click();
if (!alreadyAuthenticated) {
await waitForElement(By.id('inputUsername'));
await browser.findElement(By.id('inputUsername')).sendKeys(username);
await browser.findElement(By.id('inputPassword')).sendKeys(password);
await browser.findElement(By.id('loginSubmitButton')).click(); await browser.findElement(By.id('loginSubmitButton')).click();
await browser.sleep(2000);
athenticated_by_oidc = true;
} }
await waitForElement(By.xpath('//p[@class="confirm-trust" and contains(., "Continuing will grant ")]')); await waitForElement(By.xpath('//p[@class="confirm-trust" and contains(., "Continuing will grant ")]'));
await browser.findElement(By.xpath('//a[contains(., "Continue")]')).click(); await browser.findElement(By.xpath('//a[contains(., "Continue")]')).click();
await browser.sleep(2000);
if (proceedWithReset) { if (await browser.findElements(By.xpath('//div[@aria-label="Skip verification for now"]')).then(found => !!found.length)) {
await waitForElement(By.xpath('//div[text()="Proceed with reset" or text()="Reset all"]')); await skipVerification();
if (await browser.findElements(By.xpath('//div[text()="Reset all"]')).then(found => !!found.length)) {
await browser.findElement(By.xpath('//div[text()="Reset all"]')).click();
}
await waitForElement(By.xpath('//div[text()="Proceed with reset"]'));
await browser.findElement(By.xpath('//div[text()="Proceed with reset"]')).click();
await waitForElement(By.xpath('//button[@class="mx_Dialog_primary" and text()="Continue"] | //div[@class="mx_EncryptionCard_buttons"]/button[@data-kind="primary"]'));
await browser.findElement(By.xpath('//button[@class="mx_Dialog_primary" and text()="Continue"] | //div[@class="mx_EncryptionCard_buttons"]/button[@data-kind="primary"]')).click();
await waitForElement(By.xpath('//button[@class="mx_Dialog_primary" and text()="Continue"] | //div[@class="mx_EncryptionCard_buttons"]/button[@data-kind="primary"]'));
await browser.findElement(By.xpath('//button[@class="mx_Dialog_primary" and text()="Continue"] | //div[@class="mx_EncryptionCard_buttons"]/button[@data-kind="primary"]')).click();
await waitForElement(By.xpath('//button[text()="Done"] | //div[text()="Single Sign On"]'));
if (await browser.findElements(By.xpath('//div[text()="Single Sign On"]')).then(found => !!found.length)) {
await browser.findElement(By.xpath('//div[text()="Single Sign On"]')).click();
const originalWindowHandle = await browser.getWindowHandle();
await browser.wait(async () => (await browser.getAllWindowHandles()).length === 2, 10000);
//Loop through until we find a new window handle
const windows = await browser.getAllWindowHandles();
windows.forEach(async handle => {
if (handle !== originalWindowHandle) {
await browser.switchTo().window(handle);
}
});
await waitForElement(By.xpath('//a[contains(., "Continue with")]'));
await browser.findElement(By.xpath('//a[contains(., "Continue with")]')).click();
// switch back to the main window
await browser.switchTo().window(originalWindowHandle);
await waitForElement(By.xpath('//div[text()="Confirm"]'));
await browser.findElement(By.xpath('//div[text()="Confirm"]')).click();
}
await waitForElement(By.xpath('//div[text()="Cancel"] | //h1[contains(., "Welcome")]'));
if (await browser.findElements(By.xpath('//div[text()="Cancel"]')).then(found => !!found.length)) {
await browser.findElement(By.xpath('//div[text()="Cancel"]')).click();
}
} }
await browser.sleep(3000); await browser.sleep(3000);
@@ -192,13 +139,17 @@ describe('Application life cycle test', function () {
} }
async function login() { async function login() {
await browser.get(`https://${elementApp.fqdn}/#/login`); await browser.get('https://' + app.fqdn + '/#/login');
await browser.wait(until.elementLocated(By.xpath('//input[@value="Sign in"]')), TEST_TIMEOUT); await browser.wait(until.elementLocated(By.xpath('//input[@value="Sign in"]')), TEST_TIMEOUT);
await browser.findElement(By.xpath('//input[@name="username"]')).sendKeys(USERNAME); await browser.findElement(By.xpath('//input[@name="username"]')).sendKeys(USERNAME);
await browser.findElement(By.xpath('//input[@name="password"]')).sendKeys(PASSWORD); await browser.findElement(By.xpath('//input[@name="password"]')).sendKeys(PASSWORD);
await browser.findElement(By.xpath('//input[@value="Sign in"]')).click(); await browser.findElement(By.xpath('//input[@value="Sign in"]')).click();
await browser.sleep(5000); await browser.sleep(5000);
await skipVerification();
if (await browser.findElements(By.xpath('//div[@aria-label="Skip verification for now"]')).then(found => !!found.length)) {
await skipVerification();
}
await browser.wait(until.elementLocated(By.xpath('//span[text()="Rooms"]')), TEST_TIMEOUT); await browser.wait(until.elementLocated(By.xpath('//span[text()="Rooms"]')), TEST_TIMEOUT);
} }
@@ -213,11 +164,11 @@ describe('Application life cycle test', function () {
} }
async function logout() { async function logout() {
await browser.get(`https://${elementApp.fqdn}/#/home`); await browser.get('https://' + app.fqdn + '/#/home');
await browser.sleep(5000); await browser.sleep(5000);
await waitForElement(By.xpath('//div[@role="button" and @aria-label="User menu"]')); await waitForElement(By.xpath('//div[@aria-label="User menu"]'));
await browser.findElement(By.xpath('//div[@role="button" and @aria-label="User menu"]')).click(); await browser.findElement(By.xpath('//div[@aria-label="User menu"]')).click();
await browser.sleep(2000); await browser.sleep(2000);
await browser.findElement(By.xpath('//li[@role="menuitem" and @aria-label="Sign out"]')).click(); await browser.findElement(By.xpath('//li[@role="menuitem" and @aria-label="Sign out"]')).click();
@@ -232,29 +183,24 @@ describe('Application life cycle test', function () {
} }
async function isLoggedIn() { async function isLoggedIn() {
await browser.get(`https://${elementApp.fqdn}/#/home`); await browser.get('https://' + app.fqdn + '/#/home');
await browser.wait(until.elementLocated(By.xpath('//span[text()="Rooms"]')), TEST_TIMEOUT); await browser.wait(until.elementLocated(By.xpath('//span[text()="Rooms"]')), TEST_TIMEOUT);
} }
async function createRoom() { async function createRoom() {
await browser.get(`https://${elementApp.fqdn}/#/home`); await browser.get('https://' + app.fqdn + '/#/home');
await browser.sleep(2000); await browser.sleep(4000);
await waitForElement(By.xpath('//div[@role="button" and @aria-label="Add room"]')); await waitForElement(By.xpath('//div[@role="button" and @aria-label="Add room"]'));
await browser.findElement(By.xpath('//div[@role="button" and @aria-label="Add room"]')).click(); await browser.findElement(By.xpath('//div[@role="button" and @aria-label="Add room"]')).click();
await browser.sleep(1000); await browser.sleep(2000);
await waitForElement(By.xpath('//li[@role="menuitem" and @aria-label="New room"]'));
await browser.findElement(By.xpath('//li[@role="menuitem" and @aria-label="New room"]')).click(); await browser.findElement(By.xpath('//li[@role="menuitem" and @aria-label="New room"]')).click();
await browser.sleep(1000); await browser.sleep(2000);
await waitForElement(By.xpath('//input[@label="Name"]'));
await browser.findElement(By.xpath('//input[@label="Name"]')).sendKeys(ROOM_NAME); await browser.findElement(By.xpath('//input[@label="Name"]')).sendKeys(ROOM_NAME);
await browser.sleep(2000);
await browser.sleep(1000);
await waitForElement(By.xpath('//button[text()="Create room"]'));
await browser.findElement(By.xpath('//button[text()="Create room"]')).click(); await browser.findElement(By.xpath('//button[text()="Create room"]')).click();
await browser.sleep(2000);
await browser.sleep(1000);
await waitForElement(By.xpath('//div[@role="button" and @aria-label="Add room"]')); await waitForElement(By.xpath('//div[@role="button" and @aria-label="Add room"]'));
@@ -262,7 +208,7 @@ describe('Application life cycle test', function () {
} }
async function checkRoom() { async function checkRoom() {
await browser.get(`https://${elementApp.fqdn}/#/home`); await browser.get('https://' + app.fqdn + '/#/home');
await browser.sleep(4000); await browser.sleep(4000);
await waitForElement(By.xpath('//div[@role="treeitem" and @aria-label="' + ROOM_NAME + '"]')); await waitForElement(By.xpath('//div[@role="treeitem" and @aria-label="' + ROOM_NAME + '"]'));
await browser.findElement(By.xpath('//div[@role="treeitem" and @aria-label="' + ROOM_NAME + '"]')).click(); await browser.findElement(By.xpath('//div[@role="treeitem" and @aria-label="' + ROOM_NAME + '"]')).click();
@@ -287,20 +233,22 @@ describe('Application life cycle test', function () {
it('can get app information', getAppInfo); it('can get app information', getAppInfo);
it('check landing page', checkLandingPage); it('check landing page', checkLandingPage);
it('can install element-web app (no sso)', function () { execSync('cloudron install --appstore-id im.riot.cloudronapp --location ' + ELEMENT_LOCATION, EXEC_ARGS); }); it('can install element-web app', function () { execSync('cloudron install --appstore-id im.riot.cloudronapp --location ' + ELEMENT_LOCATION, EXEC_ARGS); });
it('update element-app config', updateSynapseConfig); it('update element-app config', updateSynapseConfig);
it('can get Element app info', getElementAppInfo); it('can get Element app info', getElementAppInfo);
it('can register new user', registerUser); it('can register new user', registerUser);
it('create room', createRoom); it('create room', createRoom);
it('can send message', sendMessage); it('can send message', sendMessage);
it('can logout', logout); // from auto-login
it('can logout', logout);
it('can login', login); it('can login', login);
it('check room', checkRoom); it('check room', checkRoom);
it('can logout', logout); it('can logout', logout);
it('can get app info', getAppInfo);
it('uninstall element-web app', async function () { it('uninstall element-web app', async function () {
await browser.get('about:blank'); await browser.get('about:blank');
execSync(`cloudron uninstall --app ${ELEMENT_LOCATION}`, EXEC_ARGS); execSync(`cloudron uninstall --app ${ELEMENT_LOCATION}`, EXEC_ARGS);
@@ -308,24 +256,26 @@ describe('Application life cycle test', function () {
it('uninstall app', function () { execSync('cloudron uninstall --app ' + app.id, EXEC_ARGS); }); it('uninstall app', function () { execSync('cloudron uninstall --app ' + app.id, EXEC_ARGS); });
// SSO // SSO
it('install app (sso)', function () { execSync('cloudron install --location ' + LOCATION, EXEC_ARGS); }); it('install app', function () { execSync('cloudron install --location ' + LOCATION, EXEC_ARGS); });
it('can get app info', getAppInfo); it('can get app info', getAppInfo);
it('can install element-web app (sso)', function () { execSync('cloudron install --appstore-id im.riot.cloudronapp --location ' + ELEMENT_LOCATION, EXEC_ARGS); }); it('can install element-web app', function () { execSync('cloudron install --appstore-id im.riot.cloudronapp --location ' + ELEMENT_LOCATION, EXEC_ARGS); });
it('can get Element app info', getElementAppInfo);
it('update element-app config', updateSynapseConfig); it('update element-app config', updateSynapseConfig);
it('can login via OIDC', loginOIDC.bind(null, USERNAME, PASSWORD, false, false)); it('can get Element app info', getElementAppInfo);
it('can login via OIDC', loginOIDC.bind(null, USERNAME, PASSWORD));
it('create room', createRoom); it('create room', createRoom);
it('can send message', sendMessage); it('can send message', sendMessage);
it('can get app info', getAppInfo); it('can get app info', getAppInfo);
it('can restart app', function () { execSync(`cloudron restart --app ${app.id}`); }); it('can restart app', function () { execSync(`cloudron restart ${app.id}`); });
it('backup app', function () { execSync(`cloudron backup create --app ${app.id}`, EXEC_ARGS); }); it('backup app', function () { execSync(`cloudron backup create --app ${app.id}`, EXEC_ARGS); });
it('can get Element app info', getElementAppInfo);
it('is logged in', isLoggedIn); it('is logged in', isLoggedIn);
it('check room', checkRoom); it('check room', checkRoom);
it('can get app info', getAppInfo);
it('restore app', async function () { it('restore app', async function () {
const backups = JSON.parse(execSync(`cloudron backup list --raw --app ${app.id}`)); const backups = JSON.parse(execSync(`cloudron backup list --raw --app ${app.id}`));
@@ -339,65 +289,65 @@ describe('Application life cycle test', function () {
execSync(`cloudron restore --backup ${backups[0].id} --app ${app.id}`, EXEC_ARGS); execSync(`cloudron restore --backup ${backups[0].id} --app ${app.id}`, EXEC_ARGS);
}); });
it('can get Element app info', getElementAppInfo);
it('is logged in', isLoggedIn); it('is logged in', isLoggedIn);
it('check room', checkRoom); it('check room', checkRoom);
it('can send message', sendMessage); it('can send message', sendMessage);
it('can logout', logout); it('can logout', logout);
it('can get app info', getAppInfo); it('can get app info', getAppInfo);
// web ui also throws random errors after changing domain it('move to different location', async function () {
xit('move to different location (skipped since no matrix support)', async function () {
browser.manage().deleteAllCookies(); browser.manage().deleteAllCookies();
await browser.get('about:blank'); await browser.get('about:blank');
execSync(`cloudron configure --location ${LOCATION}2`, EXEC_ARGS); execSync(`cloudron configure --location ${LOCATION}2`, EXEC_ARGS);
getAppInfo(); getAppInfo();
await browser.sleep(15000); // wait when all services are up and running
await sleep(15000);
}); });
xit('update element-app config', updateSynapseConfig);
xit('can get Element app info', getElementAppInfo); it('update element-app config', updateSynapseConfig);
xit('can login via OIDC', loginOIDC.bind(null, USERNAME, PASSWORD, true, true));
xit('check room', checkRoom); it('can get Element app info', getElementAppInfo);
xit('can send message', sendMessage); it('can login via OIDC', loginOIDC.bind(null, USERNAME, PASSWORD));
it('check room', checkRoom);
it('can send message', sendMessage);
it('can logout', logout);
it('can get app info', getAppInfo);
it('uninstall app', async function () { it('uninstall app', async function () {
await browser.get('about:blank'); await browser.get('about:blank');
execSync(`cloudron uninstall --app ${app.id}`, EXEC_ARGS); execSync(`cloudron uninstall --app ${app.id}`, EXEC_ARGS);
}); });
it('uninstall element-web app', function () {
execSync(`cloudron uninstall --app ${ELEMENT_LOCATION}`, EXEC_ARGS);
});
// test update // test update
it('clear cache', clearCache);
it('can install app for update', function () { execSync('cloudron install --appstore-id org.matrix.synapse --location ' + LOCATION, EXEC_ARGS); }); it('can install app for update', function () { execSync('cloudron install --appstore-id org.matrix.synapse --location ' + LOCATION, EXEC_ARGS); });
it('can get app info', getAppInfo); it('can get app info', getAppInfo);
it('can install element-web app (update)', function () { execSync('cloudron install --appstore-id im.riot.cloudronapp --location ' + ELEMENT_LOCATION, EXEC_ARGS); });
it('can get Element app info', getElementAppInfo);
it('update element-app config', updateSynapseConfig); it('update element-app config', updateSynapseConfig);
it('can login via OIDC', loginOIDC.bind(null, USERNAME, PASSWORD, false, false)); it('can get Element app info', getElementAppInfo);
it('can login via OIDC', loginOIDC.bind(null, USERNAME, PASSWORD));
it('is logged in', isLoggedIn); it('is logged in', isLoggedIn);
it('create room', createRoom); it('create room', createRoom);
it('can send message', sendMessage); it('can send message', sendMessage);
it('can logout', logout); it('can logout', logout);
it('clear cache', clearCache); it('can get app info', getAppInfo);
it('can update', async function () { it('can update', async function () {
await browser.get('about:blank'); await browser.get('about:blank');
execSync(`cloudron update --app ${app.id}`, EXEC_ARGS); execSync(`cloudron update --app ${app.id}`, EXEC_ARGS);
await browser.sleep(15000); // wait when all services are up and running
await sleep(15000);
}); });
it('can get Element app info', getElementAppInfo); it('can get Element app info', getElementAppInfo);
it('can login via OIDC', loginOIDC.bind(null, USERNAME, PASSWORD, false, true)); it('can login via OIDC', loginOIDC.bind(null, USERNAME, PASSWORD));
it('is logged in', isLoggedIn); it('is logged in', isLoggedIn);
it('check room', checkRoom); it('check room', checkRoom);
it('can send message', sendMessage); it('can send message', sendMessage);
it('can get app info', getAppInfo);
it('uninstall app', async function () { it('uninstall app', async function () {
await browser.get('about:blank'); await browser.get('about:blank');