Compare commits
89 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
5a5d94ce7a | ||
|
2746b36286 | ||
|
ab8ad38b85 | ||
|
d5db8f1c55 | ||
|
bc2d1c99d1 | ||
|
2381760ce1 | ||
|
680522aaaf | ||
|
60cf2dcf03 | ||
|
ab6bd4043f | ||
|
794650a646 | ||
|
f038bf5d67 | ||
|
0c10d06b47 | ||
|
056b8e6e42 | ||
|
56d4cee9c8 | ||
|
3432246e5e | ||
|
86e97c91fe | ||
|
70e1890001 | ||
|
bdb97eda2f | ||
|
0da60dccf0 | ||
|
94ea75bfdb | ||
|
4653d689d8 | ||
|
822e7fae94 | ||
|
aa44cf613d | ||
|
f084b95d66 | ||
|
30203a4fae | ||
|
363b3bcbfe | ||
|
cf6e0aa31e | ||
|
8fdae7271a | ||
|
a37c8c398f | ||
|
365763a684 | ||
|
6ec68a57e5 | ||
|
8d35c6b967 | ||
|
c9ed0c7342 | ||
|
eb246a1d9b | ||
|
f59f9b73da | ||
|
fe4d7e7bb3 | ||
|
4999cf00b1 | ||
|
e507297c6e | ||
|
734dd6c167 | ||
|
fc14c89b3e | ||
|
a0e893fbde | ||
|
8a4cdc2b03 | ||
|
b6945531b8 | ||
|
b5a542e2b1 | ||
|
1565a0f774 | ||
|
4dbbc317a8 | ||
|
53a09ffee2 | ||
|
bb0d170b27 | ||
|
f9360a5752 | ||
|
afd9d1646c | ||
|
abb8c8b871 | ||
|
0daf95ec34 | ||
|
4ab0863f24 | ||
|
4957e1f484 | ||
|
dd97a49741 | ||
|
0bc71eaa5b | ||
|
a0dc7f4558 | ||
|
9e3d0a4937 | ||
|
52b52d1a0f | ||
|
fc9323506f | ||
|
f33dc5bc7e | ||
|
39f43c1749 | ||
|
abc9b953ec | ||
|
2c7d09785a | ||
|
28760e473c | ||
|
25fc82e634 | ||
|
f2d5cadcb4 | ||
|
7a7ff78370 | ||
|
9de136492f | ||
|
9f3c2cc71c | ||
|
e00970a7ac | ||
|
92b658e10f | ||
|
8addbf5eb5 | ||
|
5dd2d5ff29 | ||
|
2800d92f14 | ||
|
c97fa9157a | ||
|
fdd9ac34ae | ||
|
d090334699 | ||
|
0c4156dce9 | ||
|
42321405b4 | ||
|
7da7a5307b | ||
|
faaf81f0c4 | ||
|
2754b1f075 | ||
|
709feb60bc | ||
|
60ec7830dd | ||
|
5e5c2b96f5 | ||
|
ddd348b09a | ||
|
a333a0cfb0 | ||
|
b08767dc17 |
146
CHANGELOG.md
146
CHANGELOG.md
@@ -37,3 +37,149 @@
|
|||||||
* Update traccar to 5.4
|
* Update traccar to 5.4
|
||||||
* [Full changelog](https://github.com/traccar/traccar/releases/tag/v5.4)
|
* [Full changelog](https://github.com/traccar/traccar/releases/tag/v5.4)
|
||||||
|
|
||||||
|
[1.1.0]
|
||||||
|
* Update traccar to 5.5
|
||||||
|
* [Full changelog](https://github.com/traccar/traccar/releases/tag/v5.5)
|
||||||
|
|
||||||
|
[1.2.0]
|
||||||
|
* Update base image to 4.0.0
|
||||||
|
|
||||||
|
[1.2.1]
|
||||||
|
* Add H02 port 5013
|
||||||
|
|
||||||
|
[1.2.2]
|
||||||
|
* Update traccar to 5.6
|
||||||
|
* [Full changelog](https://github.com/traccar/traccar/releases/tag/v5.6)
|
||||||
|
|
||||||
|
[1.3.0]
|
||||||
|
* Update traccar to 5.7
|
||||||
|
* [Full changelog](https://github.com/traccar/traccar/releases/tag/v5.7)
|
||||||
|
|
||||||
|
[1.4.0]
|
||||||
|
* Add support for Telefonika TMT250 Port 5027
|
||||||
|
|
||||||
|
[1.5.0]
|
||||||
|
* Update traccar to 5.8
|
||||||
|
* [Full changelog](https://github.com/traccar/traccar/releases/tag/v5.8)
|
||||||
|
|
||||||
|
[1.5.1]
|
||||||
|
* Update traccar to 5.9
|
||||||
|
* [Full changelog](https://github.com/traccar/traccar/releases/tag/v5.9)
|
||||||
|
|
||||||
|
[1.6.0]
|
||||||
|
* Update base image to 4.2.0
|
||||||
|
|
||||||
|
[1.7.0]
|
||||||
|
* Update traccar to 5.10
|
||||||
|
* [Full changelog](https://github.com/traccar/traccar/releases/tag/v5.10)
|
||||||
|
* [Release Announcement](https://www.traccar.org/blog/traccar-5-10/)
|
||||||
|
* Two-factor authentication using TOTP
|
||||||
|
* Event to notify about sent queued commands
|
||||||
|
* Option to access last position in computed attributes
|
||||||
|
* Unification of OBD speed units
|
||||||
|
* Event buffer limit in the web app (should improve performance)
|
||||||
|
* Automatic update check for the web app
|
||||||
|
|
||||||
|
[1.7.1]
|
||||||
|
* Update traccar to 5.11
|
||||||
|
* [Full changelog](https://github.com/traccar/traccar/releases/tag/v5.11)
|
||||||
|
* Update web submodule
|
||||||
|
|
||||||
|
[1.7.2]
|
||||||
|
* Update traccar to 5.12
|
||||||
|
* [Full changelog](https://www.traccar.org/blog/traccar-5-12/)
|
||||||
|
|
||||||
|
[1.7.3]
|
||||||
|
* Only create admin account on fresh installation
|
||||||
|
|
||||||
|
[1.8.0]
|
||||||
|
* Update traccar to 6.0
|
||||||
|
* [Full changelog](https://www.traccar.org/blog/traccar-6-0/)
|
||||||
|
|
||||||
|
[1.9.0]
|
||||||
|
* Update traccar to 6.1
|
||||||
|
* [Full changelog](https://www.traccar.org/blog/traccar-6-1/)
|
||||||
|
|
||||||
|
[1.10.0]
|
||||||
|
* Update traccar to 6.2
|
||||||
|
* [Full changelog](https://www.traccar.org/blog/traccar-6-2/)
|
||||||
|
* Computed attributes can now be ordered using priority
|
||||||
|
* Support token authentication for WebSocket
|
||||||
|
* Allow regular users to edit hours and total distance
|
||||||
|
* Support for right-to-left languages on map
|
||||||
|
* Terms and privacy policy option
|
||||||
|
* Engine hours are now calculated after computed attributes
|
||||||
|
* Default configuration file is now removed to avoid confusion and misconfiguration
|
||||||
|
|
||||||
|
[1.11.0]
|
||||||
|
* Migrate to OIDC login
|
||||||
|
|
||||||
|
[1.11.1]
|
||||||
|
* Fix bug where OIDC configuration was cleared in non-sso mode
|
||||||
|
|
||||||
|
[1.12.0]
|
||||||
|
* Update traccar to 6.3
|
||||||
|
* [Full changelog](https://www.traccar.org/blog/traccar-6-3/)
|
||||||
|
* Health check on the volume of stored messages
|
||||||
|
* Fix push notifications for read-only users
|
||||||
|
* Use official Google Map tiles with an API key
|
||||||
|
* Add Google traffic overlay
|
||||||
|
* New reverse geocoding options
|
||||||
|
* Faster device removal without removing history
|
||||||
|
* Avoid duplicated tasks with horizontal scaling
|
||||||
|
* Add a users column to the device list
|
||||||
|
* Clear attribute on null computation result
|
||||||
|
|
||||||
|
[1.13.0]
|
||||||
|
* Update traccar to 6.4
|
||||||
|
* [Full changelog](https://www.traccar.org/blog/traccar-6-4/)
|
||||||
|
* critical fix for device freezing issue
|
||||||
|
|
||||||
|
[1.14.0]
|
||||||
|
* Update traccar to 6.5
|
||||||
|
* [Full changelog](https://www.traccar.org/blog/traccar-6-5/)
|
||||||
|
* Handling processing errors to fix freezing devices
|
||||||
|
* Option to use linked driver as the current driver
|
||||||
|
* Support multiple alarms in a single position
|
||||||
|
* Improve web app loading experience
|
||||||
|
* Google Maps fallback option with no API key
|
||||||
|
* Wialon position forwarding option
|
||||||
|
* Fix map attribution control
|
||||||
|
|
||||||
|
[1.15.0]
|
||||||
|
* Update traccar to 6.6
|
||||||
|
* [Full Changelog](https://www.traccar.org/blog/traccar-6-6/)
|
||||||
|
* Managers can now send announcements
|
||||||
|
* Fixes for multiline SMS notifications
|
||||||
|
* Early and late computed attributes
|
||||||
|
* Improvements to user session security
|
||||||
|
* Support for custom navigation links
|
||||||
|
* Enhanced speed color scheme
|
||||||
|
* Collapsible settings and reports drawer
|
||||||
|
* Improved device card UI
|
||||||
|
|
||||||
|
[1.16.0]
|
||||||
|
* Update base image to 5.0.0
|
||||||
|
|
||||||
|
[1.17.0]
|
||||||
|
* Update traccar to 6.7.1
|
||||||
|
* [Full Changelog](https://www.traccar.org/blog/traccar-6-7.1/)
|
||||||
|
* Breaking change: Updated database schema to version 12
|
||||||
|
* Feature: Added support for new GPS device models
|
||||||
|
* Feature: Improved geofencing accuracy
|
||||||
|
* Bugfix: Fixed issue with device disconnection
|
||||||
|
* Bugfix: Resolved memory leak in server module
|
||||||
|
* Bugfix: Corrected timezone handling in reports
|
||||||
|
|
||||||
|
[1.17.1]
|
||||||
|
* Update traccar to 6.7.2
|
||||||
|
|
||||||
|
[1.17.2]
|
||||||
|
* fix OpenID login from mobile apps
|
||||||
|
|
||||||
|
[1.17.3]
|
||||||
|
* Update traccar to 6.7.3
|
||||||
|
|
||||||
|
[1.18.0]
|
||||||
|
* Update traccar to 6.8.1
|
||||||
|
|
||||||
|
@@ -5,9 +5,9 @@
|
|||||||
"description": "file://DESCRIPTION.md",
|
"description": "file://DESCRIPTION.md",
|
||||||
"changelog": "file://CHANGELOG.md",
|
"changelog": "file://CHANGELOG.md",
|
||||||
"tagline": "Modern GPS Tracking Platform",
|
"tagline": "Modern GPS Tracking Platform",
|
||||||
"version": "1.0.3",
|
"version": "1.18.0",
|
||||||
"upstreamVersion": "5.4",
|
"upstreamVersion": "6.8.1",
|
||||||
"minBoxVersion": "7.1.0",
|
"minBoxVersion": "8.1.0",
|
||||||
"memoryLimit": 1073741824,
|
"memoryLimit": 1073741824,
|
||||||
"healthCheckPath": "/",
|
"healthCheckPath": "/",
|
||||||
"httpPort": 8082,
|
"httpPort": 8082,
|
||||||
@@ -20,33 +20,64 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"addons": {
|
"addons": {
|
||||||
"ldap": {},
|
"sendmail": {
|
||||||
"sendmail": { "supportsDisplayName": false },
|
"supportsDisplayName": false
|
||||||
|
},
|
||||||
"localstorage": {},
|
"localstorage": {},
|
||||||
"mysql": {}
|
"mysql": {},
|
||||||
|
"oidc": {
|
||||||
|
"loginRedirectUri": "/api/session/openid/callback, org.traccar.manager:/api/session/openid/callback"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"optionalSso": true,
|
"optionalSso": true,
|
||||||
|
"checklist": {
|
||||||
|
"change-default-password": {
|
||||||
|
"message": "Change the admin email and password credentials"
|
||||||
|
}
|
||||||
|
},
|
||||||
"manifestVersion": 2,
|
"manifestVersion": 2,
|
||||||
"tcpPorts": {
|
"tcpPorts": {
|
||||||
"OSMAND_PORT": {
|
"OSMAND_PORT": {
|
||||||
"title": "OsmAnd Port",
|
"title": "OsmAnd Port",
|
||||||
"description": "Port over which OsmAnd clients can connect",
|
"description": "Port over which OsmAnd clients can connect",
|
||||||
"defaultValue": 5055
|
"defaultValue": 5055,
|
||||||
|
"containerPort": 5055
|
||||||
},
|
},
|
||||||
"GL200_PORT": {
|
"GL200_PORT": {
|
||||||
"title": "GL200 Protocol Port",
|
"title": "GL200 Protocol Port",
|
||||||
"description": "Port over which GL200 clients can connect",
|
"description": "Port over which GL200 clients can connect",
|
||||||
"defaultValue": 5004
|
"defaultValue": 5004,
|
||||||
|
"containerPort": 5004
|
||||||
},
|
},
|
||||||
"GPS103_PORT": {
|
"GPS103_PORT": {
|
||||||
"title": "GPS103 Protocol Port",
|
"title": "GPS103 Protocol Port",
|
||||||
"description": "Port over which GPS103 clients can connect",
|
"description": "Port over which GPS103 clients can connect",
|
||||||
"defaultValue": 5001
|
"defaultValue": 5001,
|
||||||
|
"containerPort": 5001
|
||||||
},
|
},
|
||||||
"TAIP_PORT": {
|
"TAIP_PORT": {
|
||||||
"title": "TAIP Protocol Port",
|
"title": "TAIP Protocol Port",
|
||||||
"description": "Port over which TAIP clients can connect",
|
"description": "Port over which TAIP clients can connect",
|
||||||
"defaultValue": 5031
|
"defaultValue": 5031,
|
||||||
|
"containerPort": 5031
|
||||||
|
},
|
||||||
|
"H02_PORT": {
|
||||||
|
"title": "H02 Protocol Port",
|
||||||
|
"description": "Port over which H02 clients can connect",
|
||||||
|
"defaultValue": 5013,
|
||||||
|
"containerPort": 5013
|
||||||
|
},
|
||||||
|
"TELTOKIA_PORT": {
|
||||||
|
"title": "Teltonika Protocol Port",
|
||||||
|
"description": "Port over which Teltonika clients can connect",
|
||||||
|
"defaultValue": 5027,
|
||||||
|
"containerPort": 5027
|
||||||
|
},
|
||||||
|
"GT06_PORT": {
|
||||||
|
"title": "GT06 Protocol Port",
|
||||||
|
"description": "Port over which GT06 clients can connect",
|
||||||
|
"defaultValue": 5023,
|
||||||
|
"containerPort": 5023
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"website": "https://www.traccar.org",
|
"website": "https://www.traccar.org",
|
||||||
@@ -54,7 +85,10 @@
|
|||||||
"contactEmail": "support@cloudron.io",
|
"contactEmail": "support@cloudron.io",
|
||||||
"icon": "file://logo.png",
|
"icon": "file://logo.png",
|
||||||
"tags": [
|
"tags": [
|
||||||
"gps", "tracking", "seek", "fleet"
|
"gps",
|
||||||
|
"tracking",
|
||||||
|
"seek",
|
||||||
|
"fleet"
|
||||||
],
|
],
|
||||||
"mediaLinks": [
|
"mediaLinks": [
|
||||||
"https://screenshots.cloudron.io/org.traccar.cloudronapp/web.png",
|
"https://screenshots.cloudron.io/org.traccar.cloudronapp/web.png",
|
||||||
@@ -62,6 +96,5 @@
|
|||||||
"https://screenshots.cloudron.io/org.traccar.cloudronapp/command_new.png"
|
"https://screenshots.cloudron.io/org.traccar.cloudronapp/command_new.png"
|
||||||
],
|
],
|
||||||
"forumUrl": "https://forum.cloudron.io/category/146/traccar",
|
"forumUrl": "https://forum.cloudron.io/category/146/traccar",
|
||||||
"documentationUrl": "https://docs.cloudron.io/apps/traccar"
|
"documentationUrl": "https://docs.cloudron.io/packages/traccar"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,11 +1,12 @@
|
|||||||
FROM cloudron/base:3.2.0@sha256:ba1d566164a67c266782545ea9809dc611c4152e27686fd14060332dd88263ea
|
FROM cloudron/base:5.0.0@sha256:04fd70dbd8ad6149c19de39e35718e024417c3e01dc9c6637eaf4a41ec4e596c
|
||||||
|
|
||||||
RUN mkdir -p /app/code
|
RUN mkdir -p /app/code
|
||||||
WORKDIR /app/code
|
WORKDIR /app/code
|
||||||
|
|
||||||
ARG VERSION=5.4
|
# renovate: datasource=github-releases depName=traccar/traccar versioning=regex:^(?<major>\d+)\.(?<minor>\d+)\.?(?<patch>\d+)?$ extractVersion=^v(?<version>.+)$
|
||||||
|
ARG TRACCAR_VERSION=6.8.1
|
||||||
|
|
||||||
RUN wget https://github.com/traccar/traccar/releases/download/v${VERSION}/traccar-linux-64-${VERSION}.zip -O traccar.zip && \
|
RUN wget https://github.com/traccar/traccar/releases/download/v${TRACCAR_VERSION}/traccar-linux-64-${TRACCAR_VERSION}.zip -O traccar.zip && \
|
||||||
unzip traccar.zip && \
|
unzip traccar.zip && \
|
||||||
./traccar.run --target /app/code/ --noexec && \
|
./traccar.run --target /app/code/ --noexec && \
|
||||||
rm README.txt traccar.zip traccar.run
|
rm README.txt traccar.zip traccar.run
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
This app is pre-setup with an admin account. The initial credentials are:
|
This app is pre-setup with an admin account. The initial credentials are:
|
||||||
|
|
||||||
**Username**: admin<br/>
|
**Username**: admin@cloudron.local<br/>
|
||||||
**Password**: admin<br/>
|
**Password**: admin<br/>
|
||||||
|
|
||||||
Please change the admin email and password credentials immediately.
|
<sso>
|
||||||
|
By default, Cloudron users have regular users permissions. Permissions can be updated on the user profile page in the admin back-end.
|
||||||
|
</sso>
|
||||||
|
4
renovate.json5
Normal file
4
renovate.json5
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
|
"extends": ["local>devops/renovator//default.renovate.json5"]
|
||||||
|
}
|
55
start.sh
55
start.sh
@@ -7,16 +7,39 @@ mkdir -p /run/traccar/logs /app/data/media
|
|||||||
echo -e "[client]\npassword=${CLOUDRON_MYSQL_PASSWORD}" > /run/traccar/mysql-extra
|
echo -e "[client]\npassword=${CLOUDRON_MYSQL_PASSWORD}" > /run/traccar/mysql-extra
|
||||||
readonly mysql="mysql --defaults-file=/run/traccar/mysql-extra --user=${CLOUDRON_MYSQL_USERNAME} --host=${CLOUDRON_MYSQL_HOST} -P ${CLOUDRON_MYSQL_PORT} ${CLOUDRON_MYSQL_DATABASE}"
|
readonly mysql="mysql --defaults-file=/run/traccar/mysql-extra --user=${CLOUDRON_MYSQL_USERNAME} --host=${CLOUDRON_MYSQL_HOST} -P ${CLOUDRON_MYSQL_PORT} ${CLOUDRON_MYSQL_DATABASE}"
|
||||||
|
|
||||||
|
wait_for_table() {
|
||||||
|
ret=`$mysql --skip-column-names -s -e "SHOW TABLES LIKE '$1';"`
|
||||||
|
while [ "$ret" != "$1" ]; do
|
||||||
|
echo "=> Table $1 not yet created, waiting ..."
|
||||||
|
sleep 1;
|
||||||
|
ret=`$mysql --skip-column-names -s -e "SHOW TABLES LIKE '$1';"`
|
||||||
|
echo "ret was ${ret}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
disable_registration() {
|
disable_registration() {
|
||||||
sleep 10
|
wait_for_table tc_servers;
|
||||||
echo "==> disabling registration"
|
|
||||||
|
echo "==> Disabling registration"
|
||||||
$mysql -e "UPDATE tc_servers SET registration=0 WHERE id=1"
|
$mysql -e "UPDATE tc_servers SET registration=0 WHERE id=1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensure_admin_account() {
|
||||||
|
wait_for_table tc_users;
|
||||||
|
|
||||||
|
echo "==> Ensure admin account"
|
||||||
|
count=`$mysql --skip-column-names -s -e "SELECT COUNT(*) FROM tc_users;"`
|
||||||
|
if [[ "$count" = "0" ]]; then
|
||||||
|
echo "==> Create initial admin account"
|
||||||
|
# Values are from https://github.com/traccar/traccar/blob/master/schema/changelog-3.3.xml#L179 which is not used anymore, but we still want the admin account
|
||||||
|
$mysql -e "INSERT INTO tc_users (name, email, hashedpassword, salt, administrator) VALUES ('admin', 'admin@cloudron.local', 'D33DCA55ABD4CC5BC76F2BC0B4E603FE2C6F61F4C1EF2D47', '000000000000000000000000000000000000000000000000', TRUE)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
echo "=> Ensure traccar.xml config"
|
echo "=> Ensure traccar.xml config"
|
||||||
if [[ ! -f /app/data/traccar.xml ]]; then
|
if [[ ! -f /app/data/traccar.xml ]]; then
|
||||||
cp /app/pkg/traccar.xml.template /app/data/traccar.xml
|
cp /app/pkg/traccar.xml.template /app/data/traccar.xml
|
||||||
disable_registration &
|
[[ -z "${CLOUDRON_OIDC_ISSUER:-}" ]] && sed -e 's/^.*openid\..*$//g' -i /app/data/traccar.xml # do this only first run
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "=> Ensure database settings"
|
echo "=> Ensure database settings"
|
||||||
@@ -30,20 +53,20 @@ xmlstarlet ed --inplace \
|
|||||||
# origin
|
# origin
|
||||||
xmlstarlet ed --inplace --update '//properties/entry[@key="web.url"]' -v "${CLOUDRON_APP_ORIGIN}" /app/data/traccar.xml
|
xmlstarlet ed --inplace --update '//properties/entry[@key="web.url"]' -v "${CLOUDRON_APP_ORIGIN}" /app/data/traccar.xml
|
||||||
|
|
||||||
# ldap
|
# OIDC
|
||||||
if [[ -n "${CLOUDRON_LDAP_URL:-}" ]]; then
|
if [[ -n "${CLOUDRON_OIDC_ISSUER:-}" ]]; then
|
||||||
echo "=> Ensure LDAP settings"
|
# update config file (to be removed on the next release)
|
||||||
|
sed -e 's/^.*openid.issuerUrl.*$//g' -i /app/data/traccar.xml
|
||||||
|
|
||||||
|
echo "=> Ensure OIDC settings"
|
||||||
|
# CLOUDRON_OIDC_PROVIDER_NAME is not supported
|
||||||
xmlstarlet ed --inplace \
|
xmlstarlet ed --inplace \
|
||||||
--update '//properties/entry[@key="ldap.enable"]' -v "true" \
|
--update '//properties/entry[@key="openid.clientId"]' -v "${CLOUDRON_OIDC_CLIENT_ID}" \
|
||||||
--update '//properties/entry[@key="ldap.url"]' -v "${CLOUDRON_LDAP_URL}" \
|
--update '//properties/entry[@key="openid.clientSecret"]' -v "${CLOUDRON_OIDC_CLIENT_SECRET}" \
|
||||||
--update '//properties/entry[@key="ldap.base"]' -v "${CLOUDRON_LDAP_USERS_BASE_DN}" \
|
--update '//properties/entry[@key="openid.authUrl"]' -v "${CLOUDRON_OIDC_AUTH_ENDPOINT}" \
|
||||||
--update '//properties/entry[@key="ldap.idAttribute"]' -v "username" \
|
--update '//properties/entry[@key="openid.tokenUrl"]' -v "${CLOUDRON_OIDC_TOKEN_ENDPOINT}" \
|
||||||
--update '//properties/entry[@key="ldap.searchFilter"]' -v '(|(username=:login)(mail=:login))' \
|
--update '//properties/entry[@key="openid.userInfoUrl"]' -v "${CLOUDRON_OIDC_PROFILE_ENDPOINT}" \
|
||||||
--update '//properties/entry[@key="ldap.user"]' -v "${CLOUDRON_LDAP_BIND_DN}" \
|
|
||||||
--update '//properties/entry[@key="ldap.password"]' -v "${CLOUDRON_LDAP_BIND_PASSWORD}" \
|
|
||||||
/app/data/traccar.xml
|
/app/data/traccar.xml
|
||||||
else
|
|
||||||
xmlstarlet ed --inplace --update '//properties/entry[@key="ldap.enable"]' -v "false" /app/data/traccar.xml
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# email
|
# email
|
||||||
@@ -58,6 +81,8 @@ xmlstarlet ed --inplace \
|
|||||||
--update '//properties/entry[@key="mail.smtp.password"]' -v "${CLOUDRON_MAIL_SMTP_PASSWORD}" \
|
--update '//properties/entry[@key="mail.smtp.password"]' -v "${CLOUDRON_MAIL_SMTP_PASSWORD}" \
|
||||||
/app/data/traccar.xml
|
/app/data/traccar.xml
|
||||||
|
|
||||||
|
(disable_registration; ensure_admin_account) &
|
||||||
|
|
||||||
chown -R cloudron /run/traccar /app/data
|
chown -R cloudron /run/traccar /app/data
|
||||||
|
|
||||||
# https://www.traccar.org/optimization/
|
# https://www.traccar.org/optimization/
|
||||||
|
2404
test/package-lock.json
generated
2404
test/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -10,10 +10,10 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"expect.js": "^0.3.1",
|
"expect.js": "^0.3.1",
|
||||||
"mocha": "^10.0.0",
|
"mocha": "^11.7.1",
|
||||||
"selenium-webdriver": "^4.5.0"
|
"selenium-webdriver": "^4.34.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chromedriver": "^106.0.1"
|
"chromedriver": "^138.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
109
test/test.js
109
test/test.js
@@ -1,50 +1,62 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
/* jshint esversion: 8 */
|
/* global it, xit, describe, before, after, afterEach */
|
||||||
/* global describe */
|
|
||||||
/* global before */
|
|
||||||
/* global after */
|
|
||||||
/* global it */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
require('chromedriver');
|
require('chromedriver');
|
||||||
|
|
||||||
var 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.EMAIL || !process.env.PASSWORD) {
|
if (!process.env.USERNAME || !process.env.EMAIL || !process.env.PASSWORD) {
|
||||||
console.log('EMAIL and PASSWORD env vars need to be set');
|
console.log('USERNAME, EMAIL and PASSWORD env vars need to be set');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Application life cycle test', function () {
|
describe('Application life cycle test', function () {
|
||||||
this.timeout(0);
|
this.timeout(0);
|
||||||
|
|
||||||
const LOCATION = 'test';
|
const LOCATION = process.env.LOCATION || 'test';
|
||||||
const TEST_TIMEOUT = 10000;
|
const TEST_TIMEOUT = 20000;
|
||||||
const EXEC_ARGS = { cwd: path.resolve(__dirname, '..'), stdio: 'inherit' };
|
const EXEC_ARGS = { cwd: path.resolve(__dirname, '..'), stdio: 'inherit' };
|
||||||
const ADMIN_USERNAME = 'admin'; // the login form is called email but accepts usernames
|
|
||||||
const ADMIN_PASSWORD = 'admin';
|
|
||||||
const DEVICE_NAME = 'FancyDevice';
|
const DEVICE_NAME = 'FancyDevice';
|
||||||
const DEVICE_IDENTIFIER = 'device1';
|
const DEVICE_IDENTIFIER = 'device1';
|
||||||
|
const ADMIN_USERNAME = 'admin@cloudron.local';
|
||||||
|
const ADMIN_PASSWORD = 'admin';
|
||||||
|
const USERNAME = process.env.USERNAME;
|
||||||
|
const EMAIL = process.env.EMAIL;
|
||||||
|
const PASSWORD = process.env.PASSWORD;
|
||||||
|
|
||||||
var browser, app;
|
let browser, app;
|
||||||
|
let athenticated_by_oidc = false;
|
||||||
|
|
||||||
before(function () {
|
before(function () {
|
||||||
const options = new Options().windowSize({ width: 1280, height: 1024 });
|
const chromeOptions = new Options().windowSize({ width: 1280, height: 1024 });
|
||||||
if (process.env.HEADLESS) options.addArguments('headless');
|
if (process.env.CI) chromeOptions.addArguments('no-sandbox', 'disable-dev-shm-usage', 'headless');
|
||||||
|
browser = new Builder().forBrowser('chrome').setChromeOptions(chromeOptions).build();
|
||||||
browser = new Builder().forBrowser('chrome').setChromeOptions(options).build();
|
if (!fs.existsSync('./screenshots')) fs.mkdirSync('./screenshots');
|
||||||
});
|
});
|
||||||
|
|
||||||
after(function () {
|
after(function () {
|
||||||
browser.quit();
|
browser.quit();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(async function () {
|
||||||
|
if (!process.env.CI || !app) return;
|
||||||
|
|
||||||
|
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 waitForElement(elem) {
|
async function waitForElement(elem) {
|
||||||
await browser.wait(until.elementLocated(elem), TEST_TIMEOUT);
|
await browser.wait(until.elementLocated(elem), TEST_TIMEOUT);
|
||||||
await browser.wait(until.elementIsVisible(browser.findElement(elem)), TEST_TIMEOUT);
|
await browser.wait(until.elementIsVisible(browser.findElement(elem)), TEST_TIMEOUT);
|
||||||
@@ -59,10 +71,31 @@ describe('Application life cycle test', function () {
|
|||||||
async function login(emailOrUsername, password) {
|
async function login(emailOrUsername, password) {
|
||||||
await browser.get(`https://${app.fqdn}/login`);
|
await browser.get(`https://${app.fqdn}/login`);
|
||||||
await waitForElement(By.xpath('//input[@name="email"]'));
|
await waitForElement(By.xpath('//input[@name="email"]'));
|
||||||
await browser.findElement(By.xpath('//input[@name="email"]')).sendKeys(Key.CONTROL + 'a');
|
await browser.findElement(By.xpath('//input[@name="email"]')).sendKeys(Key.CONTROL + 'a' + Key.BACK_SPACE + Key.COMMAND + 'a' + Key.BACK_SPACE);
|
||||||
await browser.findElement(By.xpath('//input[@name="email"]')).sendKeys(emailOrUsername);
|
await browser.findElement(By.xpath('//input[@name="email"]')).sendKeys(emailOrUsername);
|
||||||
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('//button[text()="Login"]')).click();
|
await browser.findElement(By.xpath('//button[text()="Login"]')).click();
|
||||||
|
await browser.sleep(3000);
|
||||||
|
await waitForElement(By.xpath('//span[text()="Account"]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loginOIDC(username, password, alreadyAuthenticated = true) {
|
||||||
|
browser.manage().deleteAllCookies();
|
||||||
|
await browser.get(`https://${app.fqdn}/login`);
|
||||||
|
await browser.sleep(2000);
|
||||||
|
|
||||||
|
await waitForElement(By.xpath('//button[contains(., "Login with OpenID")]'));
|
||||||
|
await browser.findElement(By.xpath('//button[contains(., "Login with OpenID")]')).click();
|
||||||
|
await browser.sleep(2000);
|
||||||
|
|
||||||
|
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.sleep(3000);
|
||||||
await waitForElement(By.xpath('//span[text()="Account"]'));
|
await waitForElement(By.xpath('//span[text()="Account"]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,9 +111,9 @@ describe('Application life cycle test', function () {
|
|||||||
|
|
||||||
async function addDevice() {
|
async function addDevice() {
|
||||||
await browser.get(`https://${app.fqdn}/settings/device`);
|
await browser.get(`https://${app.fqdn}/settings/device`);
|
||||||
await waitForElement(By.id(':r3:'));
|
await waitForElement(By.xpath('(//input[contains(@id, "«r")])[1]'));
|
||||||
await browser.findElement(By.id(':r3:')).sendKeys(DEVICE_NAME);
|
await browser.findElement(By.xpath('(//input[contains(@id, "«r")])[1]')).sendKeys(DEVICE_NAME);
|
||||||
await browser.findElement(By.id(':r4:')).sendKeys(DEVICE_IDENTIFIER);
|
await browser.findElement(By.xpath('(//input[contains(@id, "«r")])[2]')).sendKeys(DEVICE_IDENTIFIER);
|
||||||
await browser.findElement(By.xpath('//button[text()="Save"]')).click();
|
await browser.findElement(By.xpath('//button[text()="Save"]')).click();
|
||||||
await waitForElement(By.xpath(`//span[text()="${DEVICE_NAME}"]`));
|
await waitForElement(By.xpath(`//span[text()="${DEVICE_NAME}"]`));
|
||||||
}
|
}
|
||||||
@@ -91,7 +124,8 @@ describe('Application life cycle test', function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
xit('build app', function () { execSync('cloudron build', EXEC_ARGS); });
|
xit('build app', function () { execSync('cloudron build', EXEC_ARGS); });
|
||||||
it('install app', function () { execSync(`cloudron install --location ${LOCATION}`, EXEC_ARGS); });
|
// no sso
|
||||||
|
it('install app (no sso)', function () { execSync(`cloudron install --no-sso --location ${LOCATION}`, EXEC_ARGS); });
|
||||||
|
|
||||||
it('can get app information', getAppInfo);
|
it('can get app information', getAppInfo);
|
||||||
it('can login as admin', login.bind(null, ADMIN_USERNAME, ADMIN_PASSWORD));
|
it('can login as admin', login.bind(null, ADMIN_USERNAME, ADMIN_PASSWORD));
|
||||||
@@ -99,10 +133,22 @@ describe('Application life cycle test', function () {
|
|||||||
it('device exists', deviceExists);
|
it('device exists', deviceExists);
|
||||||
it('can logout', logout);
|
it('can logout', logout);
|
||||||
|
|
||||||
it('can login as normal user with email', login.bind(null, process.env.EMAIL, process.env.PASSWORD));
|
it('uninstall app', async function () {
|
||||||
|
// ensure we don't hit NXDOMAIN in the mean time
|
||||||
|
await browser.get('about:blank');
|
||||||
|
execSync(`cloudron uninstall --app ${app.id}`, EXEC_ARGS);
|
||||||
|
});
|
||||||
|
|
||||||
|
// sso
|
||||||
|
it('install app (sso)', function () { execSync(`cloudron install --location ${LOCATION}`, EXEC_ARGS); });
|
||||||
|
|
||||||
|
it('can get app information', getAppInfo);
|
||||||
|
it('can login as admin', login.bind(null, ADMIN_USERNAME, ADMIN_PASSWORD));
|
||||||
|
it('can add device', addDevice);
|
||||||
|
it('device exists', deviceExists);
|
||||||
it('can logout', logout);
|
it('can logout', logout);
|
||||||
|
|
||||||
it('can login as normal user with username', login.bind(null, process.env.USERNAME, process.env.PASSWORD));
|
it('can login as normal user via OIDC', loginOIDC.bind(null, process.env.USERNAME, process.env.PASSWORD, false));
|
||||||
it('can logout', logout);
|
it('can logout', logout);
|
||||||
|
|
||||||
it('can restart app', function () { execSync(`cloudron restart --app ${app.id}`); });
|
it('can restart app', function () { execSync(`cloudron restart --app ${app.id}`); });
|
||||||
@@ -124,6 +170,9 @@ describe('Application life cycle test', function () {
|
|||||||
it('device exists', deviceExists);
|
it('device exists', deviceExists);
|
||||||
it('can logout', logout);
|
it('can logout', logout);
|
||||||
|
|
||||||
|
it('can login as normal user via OIDC', loginOIDC.bind(null, process.env.USERNAME, process.env.PASSWORD));
|
||||||
|
it('can logout', logout);
|
||||||
|
|
||||||
it('move to different location', async function () {
|
it('move to different location', async function () {
|
||||||
// ensure we don't hit NXDOMAIN in the mean time
|
// ensure we don't hit NXDOMAIN in the mean time
|
||||||
await browser.get('about:blank');
|
await browser.get('about:blank');
|
||||||
@@ -135,6 +184,9 @@ describe('Application life cycle test', function () {
|
|||||||
it('device exists', deviceExists);
|
it('device exists', deviceExists);
|
||||||
it('can logout', logout);
|
it('can logout', logout);
|
||||||
|
|
||||||
|
it('can login as normal user via OIDC', loginOIDC.bind(null, process.env.USERNAME, process.env.PASSWORD));
|
||||||
|
it('can logout', logout);
|
||||||
|
|
||||||
it('uninstall app', async function () {
|
it('uninstall app', async function () {
|
||||||
// ensure we don't hit NXDOMAIN in the mean time
|
// ensure we don't hit NXDOMAIN in the mean time
|
||||||
await browser.get('about:blank');
|
await browser.get('about:blank');
|
||||||
@@ -142,20 +194,25 @@ describe('Application life cycle test', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// test update
|
// test update
|
||||||
it('can install app', function () { execSync(`cloudron install --appstore-id org.traccar.cloudronapp --location ${LOCATION}`, EXEC_ARGS); });
|
it('can install app for update', function () { execSync(`cloudron install --appstore-id org.traccar.cloudronapp --location ${LOCATION}`, EXEC_ARGS); });
|
||||||
|
|
||||||
it('can get app information', getAppInfo);
|
it('can get app information', getAppInfo);
|
||||||
it('can login', login.bind(null, ADMIN_USERNAME, ADMIN_PASSWORD));
|
it('can login', login.bind(null, ADMIN_USERNAME, ADMIN_PASSWORD));
|
||||||
it('can add device', addDevice);
|
it('can add device', addDevice);
|
||||||
it('device exists', deviceExists);
|
it('device exists', deviceExists);
|
||||||
it('can logout', logout);
|
it('can logout', logout);
|
||||||
|
|
||||||
|
it('can login as normal user via OIDC', loginOIDC.bind(null, process.env.USERNAME, process.env.PASSWORD));
|
||||||
|
it('can logout', logout);
|
||||||
|
|
||||||
it('can update', function () { execSync(`cloudron update --app ${app.id}`, EXEC_ARGS); });
|
it('can update', function () { execSync(`cloudron update --app ${app.id}`, EXEC_ARGS); });
|
||||||
|
|
||||||
it('can login', login.bind(null, ADMIN_USERNAME, ADMIN_PASSWORD));
|
it('can login', login.bind(null, ADMIN_USERNAME, ADMIN_PASSWORD));
|
||||||
it('device exists', deviceExists);
|
it('device exists', deviceExists);
|
||||||
it('can logout', logout);
|
it('can logout', logout);
|
||||||
|
|
||||||
it('can login as normal user with username', login.bind(null, process.env.USERNAME, process.env.PASSWORD));
|
// OIDC login
|
||||||
|
it('can login as normal user via OIDC', loginOIDC.bind(null, process.env.USERNAME, process.env.PASSWORD));
|
||||||
it('can logout', logout);
|
it('can logout', logout);
|
||||||
|
|
||||||
it('uninstall app', async function () {
|
it('uninstall app', async function () {
|
||||||
|
@@ -25,13 +25,11 @@
|
|||||||
|
|
||||||
<entry key='web.url'>##CLOUDRON_APP_ORIGIN##</entry>
|
<entry key='web.url'>##CLOUDRON_APP_ORIGIN##</entry>
|
||||||
|
|
||||||
<entry key='ldap.enable'>true</entry>
|
<entry key='openid.clientId'>##CLOUDRON_OIDC_CLIENT_ID##</entry>
|
||||||
<entry key='ldap.url'>##CLOUDRON_LDAP_URL##</entry>
|
<entry key='openid.clientSecret'>##CLOUDRON_OIDC_CLIENT_SECRET##</entry>
|
||||||
<entry key='ldap.base'>##CLOUDRON_LDAP_USERS_BASE_DN##</entry>
|
<entry key='openid.authUrl'>##CLOUDRON_OIDC_AUTH_ENDPOINT##</entry>
|
||||||
<entry key='ldap.idAttribute'>username</entry>
|
<entry key='openid.tokenUrl'>##CLOUDRON_OIDC_TOKEN_ENDPOINT##</entry>
|
||||||
<entry key='ldap.searchFilter'>username=:login</entry>
|
<entry key='openid.userInfoUrl'>##CLOUDRON_OIDC_PROFILE_ENDPOINT##</entry>
|
||||||
<entry key='ldap.user'>##CLOUDRON_LDAP_BIND_DN##</entry>
|
|
||||||
<entry key='ldap.password'>##CLOUDRON_LDAP_BIND_PASSWORD##</entry>
|
|
||||||
|
|
||||||
<entry key='mail.smtp.host'>smtp.gmail.com</entry>
|
<entry key='mail.smtp.host'>smtp.gmail.com</entry>
|
||||||
<entry key='mail.smtp.port'>587</entry>
|
<entry key='mail.smtp.port'>587</entry>
|
||||||
|
Reference in New Issue
Block a user