Add client side app postProcess() to fix postinstall message

This commit is contained in:
Johannes Zellner
2025-03-18 19:04:47 +01:00
parent f6f97e69eb
commit 7d07e34d6b
5 changed files with 116 additions and 65 deletions
+69 -49
View File
@@ -1,8 +1,14 @@
import { API_ORIGIN, APP_TYPES, PROXY_APP_ID, HSTATES, ISTATES, RSTATES } from '../constants.js';
import { eachLimit } from 'async';
import { fetcher } from 'pankow';
import { sleep } from 'pankow/utils';
import moment from 'moment-timezone';
import DashboardModel from './DashboardModel.js';
import ProfileModel from './ProfileModel.js';
const dashboardModel = DashboardModel.create();
const profileModel = ProfileModel.create();
function installationStateLabel(app) {
if (!app) return '';
@@ -67,6 +73,20 @@ function appProgressMessage(app) {
function create() {
const accessToken = localStorage.token;
// TODO maybe we can share those globally
let config = null;
let profile = null;
async function loadConfigAndProfile() {
let [error, result] = await dashboardModel.config();
if (error) return console.error(error);
config = result;
[error, result] = await profileModel.get();
if (error) return console.error(error);
profile = result;
}
async function getTask(appId) {
let error, result;
try {
@@ -83,6 +103,53 @@ function create() {
return result.body;
}
async function postProcess(app) {
if (!profile || !config) await loadConfigAndProfile();
app.ssoAuth = app.sso && (app.manifest.addons['ldap'] || app.manifest.addons['oidc'] || app.manifest.addons['proxyAuth']); // checking app.sso first ensures app.manifest.addons is not null
app.type = app.manifest.id === PROXY_APP_ID ? APP_TYPES.PROXIED : APP_TYPES.APP;
app.iconUrl = app.iconUrl ? `${API_ORIGIN}${app.iconUrl}?ts=${new Date(app.ts).getTime()}` : `${API_ORIGIN}/img/appicon_fallback.png`; // calculate full icon url with cache busting
// only fetch if we have permissions and a taskId is set/active
if (!app.taskId || (app.accessLevel !== 'operator' && app.accessLevel !== 'admin')) {
app.progress = 0;
app.message = '';
app.taskMinutesActive = 0;
} else {
const task = await getTask(app.id);
if (task) {
app.progress = task.percent;
app.message = task.message;
app.taskMinutesActive = moment.duration(moment.utc().diff(moment.utc(task.creationTime))).asMinutes();
} else {
app.progress = 0;
app.message = '';
app.taskMinutesActive = 0;
}
}
if (app.manifest.postInstallMessage) {
var text= app.manifest.postInstallMessage;
// we chose - because underscore has special meaning in markdown
text = text.replace(/\$CLOUDRON-APP-LOCATION/g, app.subdomain);
text = text.replace(/\$CLOUDRON-APP-DOMAIN/g, app.domain);
text = text.replace(/\$CLOUDRON-APP-FQDN/g, app.fqdn);
text = text.replace(/\$CLOUDRON-APP-ORIGIN/g, 'https://' + app.fqdn);
text = text.replace(/\$CLOUDRON-API-DOMAIN/g, config.adminFqdn);
text = text.replace(/\$CLOUDRON-API-ORIGIN/g, 'https://' + config.adminFqdn);
text = text.replace(/\$CLOUDRON-USERNAME/g, profile.username);
text = text.replace(/\$CLOUDRON-APP-ID/g, app.id);
// [^] matches even newlines. '?' makes it non-greedy
if (app.sso) text = text.replace(/<nosso>[^]*?<\/nosso>/g, '');
else text = text.replace(/<sso>[^]*?<\/sso>/g, '');
app.manifest.postInstallMessage = text;
}
return app;
}
return {
name: 'AppsModel',
getTask,
@@ -133,30 +200,7 @@ function create() {
if (error || result.status !== 200) return [error || result];
for (const app of result.body.apps) {
app.ssoAuth = app.sso && (app.manifest.addons['ldap'] || app.manifest.addons['oidc'] || app.manifest.addons['proxyAuth']); // checking app.sso first ensures app.manifest.addons is not null
app.type = app.manifest.id === PROXY_APP_ID ? APP_TYPES.PROXIED : APP_TYPES.APP;
app.iconUrl = app.iconUrl ? `${API_ORIGIN}${app.iconUrl}?ts=${new Date(app.ts).getTime()}` : `${API_ORIGIN}/img/appicon_fallback.png`; // calculate full icon url with cache busting
// only fetch if we have permissions and a taskId is set/active
if (!app.taskId || (app.accessLevel !== 'operator' && app.accessLevel !== 'admin')) {
app.progress = 0;
app.message = '';
app.taskMinutesActive = 0;
continue;
}
const task = await getTask(app.id);
if (task) {
app.progress = task.percent;
app.message = task.message;
app.taskMinutesActive = moment.duration(moment.utc().diff(moment.utc(task.creationTime))).asMinutes();
} else {
app.progress = 0;
app.message = '';
app.taskMinutesActive = 0;
}
}
await eachLimit(result.body.apps, 10, postProcess);
return [null, result.body.apps];
},
@@ -170,31 +214,7 @@ function create() {
if (error || result.status !== 200) return [error || result];
const app = result.body;
app.ssoAuth = app.sso && (app.manifest.addons['ldap'] || app.manifest.addons['oidc'] || app.manifest.addons['proxyAuth']); // checking app.sso first ensures app.manifest.addons is not null
app.type = app.manifest.id === PROXY_APP_ID ? APP_TYPES.PROXIED : APP_TYPES.APP;
app.iconUrl = app.iconUrl ? `${API_ORIGIN}${app.iconUrl}?ts=${new Date(app.ts).getTime()}` : `${API_ORIGIN}/img/appicon_fallback.png`; // calculate full icon url with cache busting
// only fetch if we have permissions and a taskId is set/active
if (!app.taskId || (app.accessLevel !== 'operator' && app.accessLevel !== 'admin')) {
app.progress = 0;
app.message = '';
app.taskMinutesActive = 0;
} else {
const task = await getTask(app.id);
if (task) {
app.progress = task.percent;
app.message = task.message;
app.taskMinutesActive = moment.duration(moment.utc().diff(moment.utc(task.creationTime))).asMinutes();
} else {
app.progress = 0;
app.message = '';
app.taskMinutesActive = 0;
}
}
return [null, app];
return [null, await postProcess(result.body)];
},
async restart(id) {
let result;