import apps from './apps.js'; import assert from 'node:assert'; import BoxError from './boxerror.js'; import constants from './constants.js'; import debugModule from 'debug'; import eventlog from './eventlog.js'; import paths from './paths.js'; import safe from 'safetydance'; import settings from './settings.js'; const debug = debugModule('box:branding'); async function getCloudronName() { const name = await settings.get(settings.CLOUDRON_NAME_KEY); return name || 'Cloudron'; } async function setCloudronName(name, auditSource) { assert.strictEqual(typeof name, 'string'); assert(auditSource && typeof auditSource === 'object'); if (!name) throw new BoxError(BoxError.BAD_FIELD, 'name is empty'); // some arbitrary restrictions (for sake of ui layout) // if this is changed, adjust dashboard/branding.html if (name.length > 64) throw new BoxError(BoxError.BAD_FIELD, 'name cannot exceed 64 characters'); // mark apps using oidc addon to be reconfigured const [, installedApps] = await safe(apps.list()); await safe(apps.configureApps(installedApps.filter((a) => !!a.manifest.addons?.oidc), { scheduleNow: true }, auditSource), { debug }); await settings.set(settings.CLOUDRON_NAME_KEY, name); await eventlog.add(eventlog.ACTION_BRANDING_NAME, auditSource, { name }); } async function getCloudronAvatar() { let avatar = await settings.getBlob(settings.CLOUDRON_AVATAR_KEY); if (avatar) return avatar; avatar = safe.fs.readFileSync(paths.CLOUDRON_DEFAULT_AVATAR_FILE); if (avatar) return avatar; throw new BoxError(BoxError.FS_ERROR, `Could not read avatar: ${safe.error.message}`); } async function setCloudronAvatar(avatar, auditSource) { assert(Buffer.isBuffer(avatar)); assert(auditSource && typeof auditSource === 'object'); await settings.setBlob(settings.CLOUDRON_AVATAR_KEY, avatar); await eventlog.add(eventlog.ACTION_BRANDING_AVATAR, auditSource, {}); } async function getCloudronBackground() { const background = await settings.getBlob(settings.CLOUDRON_BACKGROUND_KEY); if (!background) return null; return background; } async function setCloudronBackground(background) { assert(background === null || Buffer.isBuffer(background)); await settings.setBlob(settings.CLOUDRON_BACKGROUND_KEY, background); } async function getFooter() { const value = await settings.get(settings.FOOTER_KEY); return value || constants.FOOTER; } async function renderFooter() { const footer = await getFooter(); const year = new Date().getFullYear(); return footer.replace(/%YEAR%/g, year) .replace(/%VERSION%/g, constants.VERSION); } async function setFooter(footer, auditSource) { assert.strictEqual(typeof footer, 'string'); assert(auditSource && typeof auditSource === 'object'); await settings.set(settings.FOOTER_KEY, footer); await eventlog.add(eventlog.ACTION_BRANDING_FOOTER, auditSource, { footer }); } export default { getCloudronName, setCloudronName, getCloudronAvatar, setCloudronAvatar, getCloudronBackground, setCloudronBackground, getFooter, setFooter, renderFooter };