23 Commits

Author SHA1 Message Date
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
Girish Ramakrishnan
53a09ffee2 Version 1.9.0 2024-04-11 11:49:04 +02:00
Girish Ramakrishnan
bb0d170b27 Update Traccar to 6.1 2024-04-11 09:44:19 +02:00
Johannes Zellner
f9360a5752 Bump version 2024-04-07 14:34:46 +02:00
Johannes Zellner
afd9d1646c Update test deps 2024-04-07 13:01:04 +02:00
Johannes Zellner
abb8c8b871 Update to 6.0 2024-04-07 12:59:40 +02:00
Girish Ramakrishnan
0daf95ec34 Version 1.7.3 2024-03-25 22:55:24 +01:00
Girish Ramakrishnan
4ab0863f24 Update test packages 2024-03-25 22:40:31 +01:00
Girish Ramakrishnan
4957e1f484 chain the commands 2024-03-25 22:39:00 +01:00
Girish Ramakrishnan
dd97a49741 only create admin account the first time
when importing an external traccar with on admin, this ends up
creating an admin
2024-03-25 22:24:19 +01:00
Johannes Zellner
0bc71eaa5b Bump version 2024-01-27 19:41:43 +01:00
Johannes Zellner
a0dc7f4558 Update test deps 2024-01-27 19:31:48 +01:00
Johannes Zellner
9e3d0a4937 Update to 5.12 2024-01-27 19:31:38 +01:00
Johannes Zellner
52b52d1a0f Bump version 2024-01-15 10:33:07 +01:00
Johannes Zellner
fc9323506f Update test deps 2024-01-15 09:54:49 +01:00
Johannes Zellner
f33dc5bc7e Update to version 5.11 2024-01-15 09:54:19 +01:00
Girish Ramakrishnan
39f43c1749 Version 1.7.0 2023-11-22 10:20:25 +01:00
Girish Ramakrishnan
abc9b953ec Update test packages 2023-11-22 10:04:33 +01:00
Girish Ramakrishnan
2c7d09785a Update Traccar to 5.10 2023-11-22 09:22:08 +01:00
9 changed files with 762 additions and 276 deletions

View File

@@ -69,3 +69,48 @@
[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

View File

@@ -5,8 +5,8 @@
"description": "file://DESCRIPTION.md",
"changelog": "file://CHANGELOG.md",
"tagline": "Modern GPS Tracking Platform",
"version": "1.6.0",
"upstreamVersion": "5.9",
"version": "1.11.0",
"upstreamVersion": "6.2",
"minBoxVersion": "7.1.0",
"memoryLimit": 1073741824,
"healthCheckPath": "/",
@@ -20,10 +20,10 @@
}
},
"addons": {
"ldap": {},
"sendmail": { "supportsDisplayName": false },
"localstorage": {},
"mysql": {}
"mysql": {},
"oidc": { "loginRedirectUri": "/api/session/openid/callback" }
},
"optionalSso": true,
"manifestVersion": 2,

View File

@@ -3,7 +3,7 @@ FROM cloudron/base:4.2.0@sha256:46da2fffb36353ef714f97ae8e962bd2c212ca091108d768
RUN mkdir -p /app/code
WORKDIR /app/code
ARG VERSION=5.9
ARG VERSION=6.2
RUN wget https://github.com/traccar/traccar/releases/download/v${VERSION}/traccar-linux-64-${VERSION}.zip -O traccar.zip && \
unzip traccar.zip && \

View File

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

View File

@@ -28,7 +28,7 @@ ensure_admin_account() {
wait_for_table tc_users;
echo "==> Ensure admin account"
count=`$mysql --skip-column-names -s -e "SELECT COUNT(*) FROM tc_users WHERE name='admin';"`
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
@@ -52,20 +52,29 @@ 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"
# get rid of ldap, can be removed in the next release
sed -e 's/ldap.url/openid.clientId/g' \
-e 's/ldap.base/openid.clientSecret/g' \
-e 's/ldap.idAttribute/openid.issuerUrl/g' \
-e 's/ldap.searchFilter/openid.authUrl/g' \
-e 's/ldap.user/openid.tokenUrl/g' \
-e 's/ldap.password/openid.userInfoUrl/g' \
-e 's/^.*ldap\..*$//g' \
-i /app/data/traccar.xml
# OIDC
if [[ -n "${CLOUDRON_OIDC_ISSUER:-}" ]]; then
echo "=> Ensure OIDC settings"
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.issuerUrl"]' -v "${CLOUDRON_OIDC_ISSUER}" \
--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
sed -e 's/^.*openid\..*$//g' -i /app/data/traccar.xml
fi
# email
@@ -80,8 +89,7 @@ xmlstarlet ed --inplace \
--update '//properties/entry[@key="mail.smtp.password"]' -v "${CLOUDRON_MAIL_SMTP_PASSWORD}" \
/app/data/traccar.xml
disable_registration &
ensure_admin_account &
(disable_registration; ensure_admin_account) &
chown -R cloudron /run/traccar /app/data

850
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.2.0",
"selenium-webdriver": "^4.14.0"
"mocha": "^10.4.0",
"selenium-webdriver": "^4.21.0"
},
"dependencies": {
"chromedriver": "^118.0.1"
"chromedriver": "^125.0.3"
}
}

View File

@@ -10,14 +10,14 @@
require('chromedriver');
var execSync = require('child_process').execSync,
const execSync = require('child_process').execSync,
expect = require('expect.js'),
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);
}
@@ -25,16 +25,18 @@ describe('Application life cycle test', function () {
this.timeout(0);
const LOCATION = 'test';
const TEST_TIMEOUT = 10000;
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;
var browser, app;
let browser, app;
let athenticated_by_oidc = false;
before(function () {
const options = new Options().windowSize({ width: 1280, height: 1024 });
@@ -61,10 +63,35 @@ 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) {
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 (!athenticated_by_oidc) {
await waitForElement(By.xpath('//input[@name="username"]'));
await browser.findElement(By.xpath('//input[@name="username"]')).sendKeys(username);
await browser.findElement(By.xpath('//input[@name="password"]')).sendKeys(password);
await browser.sleep(2000);
await browser.findElement(By.xpath('//button[@type="submit" and contains(text(), "Sign in")]')).click();
await browser.sleep(2000);
athenticated_by_oidc = true;
}
await browser.sleep(3000);
await waitForElement(By.xpath('//span[text()="Account"]'));
}
@@ -93,7 +120,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 +129,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));
it('can logout', logout);
it('can restart app', function () { execSync(`cloudron restart --app ${app.id}`); });
@@ -126,6 +166,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 +180,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 +190,26 @@ 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);
// LDAP login
it('can login as normal user with email', login.bind(null, process.env.EMAIL, 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,12 @@
<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.issuerUrl'>##CLOUDRON_OIDC_ISSUER##</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>