35 Commits

Author SHA1 Message Date
Package Updates
0c10d06b47 Update package version to 1.17.0 2025-05-27 09:26:41 +00:00
Vladimir D
056b8e6e42 OIDC config fixed 2025-05-27 13:12:48 +04:00
Vladimir D
56d4cee9c8 tests updated 2025-05-27 12:30:17 +04:00
Renovate Bot
3432246e5e chore(deps): update dependency traccar/traccar to v6.7.1
| datasource      | package         | from | to    |
| --------------- | --------------- | ---- | ----- |
| github-releases | traccar/traccar | 6.6  | 6.7.1 |
2025-05-24 05:21:15 +00:00
Package Updates
86e97c91fe Update package version to 1.16.0 2025-04-01 15:48:05 +00:00
Girish Ramakrishnan
70e1890001 Update base image to 5.0.0 2025-04-01 17:32:33 +02:00
Package Updates
bdb97eda2f Update package version to 1.15.0 2025-01-12 08:36:48 +00:00
Renovate Bot
0da60dccf0 chore(deps): update dependency traccar/traccar to v6.6
| datasource      | package         | from | to  |
| --------------- | --------------- | ---- | --- |
| github-releases | traccar/traccar | 6.5  | 6.6 |
2025-01-12 06:21:07 +00:00
Vladimir D
94ea75bfdb "CLOUDRON_OIDC_PROVIDER_NAME is not supported" comment added
checklist added
2024-12-26 16:20:18 +04:00
Renovate Bot
4653d689d8 chore(deps): update dependency traccar/traccar to v6.5
| datasource      | package         | from | to  |
| --------------- | --------------- | ---- | --- |
| github-releases | traccar/traccar | 6.4  | 6.5 |
2024-11-11 08:29:52 +00:00
Girish Ramakrishnan
822e7fae94 Update renovate 2024-11-11 08:28:06 +00:00
Johannes Zellner
aa44cf613d Has no patch version 2024-11-10 20:45:05 +01:00
Johannes Zellner
f084b95d66 Downgrade for ci 2024-11-10 20:42:19 +01:00
Johannes Zellner
30203a4fae Prepare for ci 2024-11-10 20:42:07 +01:00
Girish Ramakrishnan
363b3bcbfe Update renovate.json5 2024-11-04 17:09:53 +00:00
Girish Ramakrishnan
cf6e0aa31e Add renovate.json5 2024-11-04 17:02:48 +00:00
Johannes Zellner
8fdae7271a Bump version 2024-09-18 13:47:27 +02:00
Johannes Zellner
a37c8c398f Make tests language independent 2024-09-18 13:40:48 +02:00
Johannes Zellner
365763a684 Update test deps 2024-09-18 11:12:51 +02:00
Johannes Zellner
6ec68a57e5 Update to 6.5 2024-09-18 11:12:34 +02:00
Girish Ramakrishnan
8d35c6b967 Version 1.13.0 2024-08-10 10:17:09 +02:00
Girish Ramakrishnan
c9ed0c7342 Update test packages 2024-08-10 10:02:48 +02:00
Girish Ramakrishnan
eb246a1d9b Update Traccar to 6.4 2024-08-10 09:49:20 +02:00
Girish Ramakrishnan
f59f9b73da Version 1.12.0 2024-07-29 09:51:07 +02:00
Girish Ramakrishnan
fe4d7e7bb3 Update test packages 2024-07-29 09:50:11 +02:00
Girish Ramakrishnan
4999cf00b1 Update Traccar to 6.3 2024-07-29 08:39:22 +02:00
Girish Ramakrishnan
e507297c6e Version 1.11.1 2024-06-13 12:00:02 +02:00
Girish Ramakrishnan
734dd6c167 delete oidc config only on first run 2024-06-13 11:14:20 +02:00
Girish Ramakrishnan
fc14c89b3e Fix up tests 2024-06-13 10:56:00 +02:00
Girish Ramakrishnan
a0e893fbde do not delete oidc config in non-sso mode 2024-06-13 10:55:52 +02:00
Girish Ramakrishnan
8a4cdc2b03 Version 1.11.0 2024-06-06 14:58:20 +02:00
Vladimir D
b6945531b8 OIDC auth implemented, tests updated 2024-06-06 15:56:06 +04:00
Girish Ramakrishnan
b5a542e2b1 Version 1.10.0 2024-06-03 11:32:29 +02:00
Girish Ramakrishnan
1565a0f774 Update test packages 2024-06-03 11:18:26 +02:00
Girish Ramakrishnan
4dbbc317a8 Update Traccar to 6.2 2024-06-03 11:04:33 +02:00
10 changed files with 1026 additions and 595 deletions

View File

@@ -100,3 +100,74 @@
* 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

View File

@@ -5,9 +5,9 @@
"description": "file://DESCRIPTION.md",
"changelog": "file://CHANGELOG.md",
"tagline": "Modern GPS Tracking Platform",
"version": "1.9.0",
"upstreamVersion": "6.1",
"minBoxVersion": "7.1.0",
"version": "1.17.0",
"upstreamVersion": "6.7.1",
"minBoxVersion": "8.1.0",
"memoryLimit": 1073741824,
"healthCheckPath": "/",
"httpPort": 8082,
@@ -20,12 +20,21 @@
}
},
"addons": {
"ldap": {},
"sendmail": { "supportsDisplayName": false },
"sendmail": {
"supportsDisplayName": false
},
"localstorage": {},
"mysql": {}
"mysql": {},
"oidc": {
"loginRedirectUri": "/api/session/openid/callback"
}
},
"optionalSso": true,
"checklist": {
"change-default-password": {
"message": "Change the admin email and password credentials"
}
},
"manifestVersion": 2,
"tcpPorts": {
"OSMAND_PORT": {
@@ -70,7 +79,10 @@
"contactEmail": "support@cloudron.io",
"icon": "file://logo.png",
"tags": [
"gps", "tracking", "seek", "fleet"
"gps",
"tracking",
"seek",
"fleet"
],
"mediaLinks": [
"https://screenshots.cloudron.io/org.traccar.cloudronapp/web.png",
@@ -80,4 +92,3 @@
"forumUrl": "https://forum.cloudron.io/category/146/traccar",
"documentationUrl": "https://docs.cloudron.io/apps/traccar"
}

View File

@@ -1,11 +1,12 @@
FROM cloudron/base:4.2.0@sha256:46da2fffb36353ef714f97ae8e962bd2c212ca091108d768ba473078319a47f4
FROM cloudron/base:5.0.0@sha256:04fd70dbd8ad6149c19de39e35718e024417c3e01dc9c6637eaf4a41ec4e596c
RUN mkdir -p /app/code
WORKDIR /app/code
ARG VERSION=6.1
# renovate: datasource=github-releases depName=traccar/traccar versioning=regex:^(?<major>\d+)\.(?<minor>\d+)\.?(?<patch>\d+)?$ extractVersion=^v(?<version>.+)$
ARG TRACCAR_VERSION=6.7.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 && \
./traccar.run --target /app/code/ --noexec && \
rm README.txt traccar.zip traccar.run

View File

@@ -3,4 +3,6 @@ This app is pre-setup with an admin account. The initial credentials are:
**Username**: admin@cloudron.local<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
View File

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

View File

@@ -39,6 +39,7 @@ ensure_admin_account() {
echo "=> Ensure traccar.xml config"
if [[ ! -f /app/data/traccar.xml ]]; then
cp /app/pkg/traccar.xml.template /app/data/traccar.xml
[[ -z "${CLOUDRON_OIDC_ISSUER:-}" ]] && sed -e 's/^.*openid\..*$//g' -i /app/data/traccar.xml # do this only first run
fi
echo "=> Ensure database settings"
@@ -52,20 +53,20 @@ xmlstarlet ed --inplace \
# origin
xmlstarlet ed --inplace --update '//properties/entry[@key="web.url"]' -v "${CLOUDRON_APP_ORIGIN}" /app/data/traccar.xml
# ldap
if [[ -n "${CLOUDRON_LDAP_URL:-}" ]]; then
echo "=> Ensure LDAP settings"
# OIDC
if [[ -n "${CLOUDRON_OIDC_ISSUER:-}" ]]; then
# 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 \
--update '//properties/entry[@key="ldap.enable"]' -v "true" \
--update '//properties/entry[@key="ldap.url"]' -v "${CLOUDRON_LDAP_URL}" \
--update '//properties/entry[@key="ldap.base"]' -v "${CLOUDRON_LDAP_USERS_BASE_DN}" \
--update '//properties/entry[@key="ldap.idAttribute"]' -v "username" \
--update '//properties/entry[@key="ldap.searchFilter"]' -v '(|(username=:login)(mail=:login))' \
--update '//properties/entry[@key="ldap.user"]' -v "${CLOUDRON_LDAP_BIND_DN}" \
--update '//properties/entry[@key="ldap.password"]' -v "${CLOUDRON_LDAP_BIND_PASSWORD}" \
--update '//properties/entry[@key="openid.clientId"]' -v "${CLOUDRON_OIDC_CLIENT_ID}" \
--update '//properties/entry[@key="openid.clientSecret"]' -v "${CLOUDRON_OIDC_CLIENT_SECRET}" \
--update '//properties/entry[@key="openid.authUrl"]' -v "${CLOUDRON_OIDC_AUTH_ENDPOINT}" \
--update '//properties/entry[@key="openid.tokenUrl"]' -v "${CLOUDRON_OIDC_TOKEN_ENDPOINT}" \
--update '//properties/entry[@key="openid.userInfoUrl"]' -v "${CLOUDRON_OIDC_PROFILE_ENDPOINT}" \
/app/data/traccar.xml
else
xmlstarlet ed --inplace --update '//properties/entry[@key="ldap.enable"]' -v "false" /app/data/traccar.xml
fi
# email

1366
test/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,10 +10,10 @@
"license": "ISC",
"devDependencies": {
"expect.js": "^0.3.1",
"mocha": "^10.4.0",
"selenium-webdriver": "^4.19.0"
"mocha": "^11.5.0",
"selenium-webdriver": "^4.33.0"
},
"dependencies": {
"chromedriver": "^123.0.3"
"chromedriver": "^136.0.3"
}
}

View File

@@ -1,10 +1,6 @@
#!/usr/bin/env node
/* jshint esversion: 8 */
/* global describe */
/* global before */
/* global after */
/* global it */
/* global it, xit, describe, before, after, afterEach */
'use strict';
@@ -12,41 +8,55 @@ require('chromedriver');
const execSync = require('child_process').execSync,
expect = require('expect.js'),
fs = require('fs'),
path = require('path'),
{ Builder, By, Key, until } = require('selenium-webdriver'),
{ Options } = require('selenium-webdriver/chrome');
if (!process.env.EMAIL || !process.env.PASSWORD) {
console.log('EMAIL and PASSWORD env vars need to be set');
if (!process.env.USERNAME || !process.env.EMAIL || !process.env.PASSWORD) {
console.log('USERNAME, EMAIL and PASSWORD env vars need to be set');
process.exit(1);
}
describe('Application life cycle test', function () {
this.timeout(0);
const LOCATION = 'test';
const TEST_TIMEOUT = 10000;
const LOCATION = process.env.LOCATION || 'test';
const TEST_TIMEOUT = 20000;
const EXEC_ARGS = { cwd: path.resolve(__dirname, '..'), stdio: 'inherit' };
const DEVICE_NAME = 'FancyDevice';
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;
let browser, app;
let athenticated_by_oidc = false;
before(function () {
const options = new Options().windowSize({ width: 1280, height: 1024 });
if (process.env.HEADLESS) options.addArguments('headless');
browser = new Builder().forBrowser('chrome').setChromeOptions(options).build();
const chromeOptions = new Options().windowSize({ width: 1280, height: 1024 });
if (process.env.CI) chromeOptions.addArguments('no-sandbox', 'disable-dev-shm-usage', 'headless');
browser = new Builder().forBrowser('chrome').setChromeOptions(chromeOptions).build();
if (!fs.existsSync('./screenshots')) fs.mkdirSync('./screenshots');
});
after(function () {
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) {
await browser.wait(until.elementLocated(elem), TEST_TIMEOUT);
await browser.wait(until.elementIsVisible(browser.findElement(elem)), TEST_TIMEOUT);
@@ -61,10 +71,31 @@ describe('Application life cycle test', function () {
async function login(emailOrUsername, password) {
await browser.get(`https://${app.fqdn}/login`);
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="password"]')).sendKeys(password);
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"]'));
}
@@ -80,9 +111,9 @@ describe('Application life cycle test', function () {
async function addDevice() {
await browser.get(`https://${app.fqdn}/settings/device`);
await waitForElement(By.id(':r3:'));
await browser.findElement(By.id(':r3:')).sendKeys(DEVICE_NAME);
await browser.findElement(By.id(':r4:')).sendKeys(DEVICE_IDENTIFIER);
await waitForElement(By.xpath('//input[@id=":r3:" or @id="«r8»"]'));
await browser.findElement(By.xpath('//input[@id=":r3:" or @id="«r8»"]')).sendKeys(DEVICE_NAME);
await browser.findElement(By.xpath('//input[@id=":r4:" or @id="«r9»"]')).sendKeys(DEVICE_IDENTIFIER);
await browser.findElement(By.xpath('//button[text()="Save"]')).click();
await waitForElement(By.xpath(`//span[text()="${DEVICE_NAME}"]`));
}
@@ -93,7 +124,8 @@ describe('Application life cycle test', function () {
}
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 login as admin', login.bind(null, ADMIN_USERNAME, ADMIN_PASSWORD));
@@ -101,10 +133,22 @@ describe('Application life cycle test', function () {
it('device exists', deviceExists);
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 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 restart app', function () { execSync(`cloudron restart --app ${app.id}`); });
@@ -126,6 +170,9 @@ describe('Application life cycle test', function () {
it('device exists', deviceExists);
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 () {
// ensure we don't hit NXDOMAIN in the mean time
await browser.get('about:blank');
@@ -137,6 +184,9 @@ describe('Application life cycle test', function () {
it('device exists', deviceExists);
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 () {
// ensure we don't hit NXDOMAIN in the mean time
await browser.get('about:blank');
@@ -144,20 +194,25 @@ describe('Application life cycle test', function () {
});
// 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 login', login.bind(null, ADMIN_USERNAME, ADMIN_PASSWORD));
it('can add device', addDevice);
it('device exists', deviceExists);
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 login', login.bind(null, ADMIN_USERNAME, ADMIN_PASSWORD));
it('device exists', deviceExists);
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('uninstall app', async function () {

View File

@@ -25,13 +25,11 @@
<entry key='web.url'>##CLOUDRON_APP_ORIGIN##</entry>
<entry key='ldap.enable'>true</entry>
<entry key='ldap.url'>##CLOUDRON_LDAP_URL##</entry>
<entry key='ldap.base'>##CLOUDRON_LDAP_USERS_BASE_DN##</entry>
<entry key='ldap.idAttribute'>username</entry>
<entry key='ldap.searchFilter'>username=:login</entry>
<entry key='ldap.user'>##CLOUDRON_LDAP_BIND_DN##</entry>
<entry key='ldap.password'>##CLOUDRON_LDAP_BIND_PASSWORD##</entry>
<entry key='openid.clientId'>##CLOUDRON_OIDC_CLIENT_ID##</entry>
<entry key='openid.clientSecret'>##CLOUDRON_OIDC_CLIENT_SECRET##</entry>
<entry key='openid.authUrl'>##CLOUDRON_OIDC_AUTH_ENDPOINT##</entry>
<entry key='openid.tokenUrl'>##CLOUDRON_OIDC_TOKEN_ENDPOINT##</entry>
<entry key='openid.userInfoUrl'>##CLOUDRON_OIDC_PROFILE_ENDPOINT##</entry>
<entry key='mail.smtp.host'>smtp.gmail.com</entry>
<entry key='mail.smtp.port'>587</entry>