diff --git a/dashboard/public/translation/en.json b/dashboard/public/translation/en.json index 3eed8c18c..122dc9e77 100644 --- a/dashboard/public/translation/en.json +++ b/dashboard/public/translation/en.json @@ -851,7 +851,9 @@ "inwxUsername": "INWX username", "inwxPassword": "INWX password", "customNameservers": "Domain uses custom (vanity) nameservers", - "zoneNamePlaceholder": "Optional. If not provided, defaults to the root domain." + "zoneNamePlaceholder": "Optional. If not provided, defaults to the root domain.", + "carddavLocation": "CardDAV server location", + "caldavLocation": "CalDAV server location" }, "removeDialog": { "title": "Remove Domain", @@ -1713,6 +1715,7 @@ "title": "Server" }, "communityapp": { - "installwarning": "Community apps are not reviewed by Cloudron. Only install apps from trusted developers. Third-party code can compromise your system." + "installwarning": "Community apps are not reviewed by Cloudron. Only install apps from trusted developers. Third-party code can compromise your system.", + "unstablewarning": "This app is marked as unstable by its developer." } } diff --git a/dashboard/src/components/WellKnownDialog.vue b/dashboard/src/components/WellKnownDialog.vue index 8806e7c15..1faac0631 100644 --- a/dashboard/src/components/WellKnownDialog.vue +++ b/dashboard/src/components/WellKnownDialog.vue @@ -15,6 +15,8 @@ const domain = ref(''); const matrixHostname = ref(''); const mastodonHostname = ref(''); const jitsiHostname = ref(''); +const carddavLocation = ref(''); +const caldavLocation = ref(''); async function onSubmit() { busy.value = true; @@ -47,6 +49,9 @@ async function onSubmit() { + ''; } + if (carddavLocation.value) wellKnown['carddav'] = carddavLocation.value; + if (caldavLocation.value) wellKnown['caldav'] = caldavLocation.value; + const [error] = await domainsModel.setWellKnown(domain.value, wellKnown); if (error) { errorMessage.value = error.body ? error.body.message : 'Internal error'; @@ -110,6 +115,16 @@ defineExpose({

{{ errorMessage }}

+ + + + + + + + + + diff --git a/src/routes/wellknown.js b/src/routes/wellknown.js index 466d74046..09b9356fd 100644 --- a/src/routes/wellknown.js +++ b/src/routes/wellknown.js @@ -10,6 +10,8 @@ async function get(req, res, next) { const [error, result] = await safe(wellknown.get(host, location)); if (error) return next(new HttpError(404, error.message)); + if (result.redirectTo) return res.redirect(302, result.redirectTo); + res.status(200).set('content-type', result.type).send(result.body); } diff --git a/src/wellknown.js b/src/wellknown.js index aef38a5dc..f9247a153 100644 --- a/src/wellknown.js +++ b/src/wellknown.js @@ -42,6 +42,18 @@ async function get(domain, location) { if (error) return new BoxError(BoxError.INTERNAL_ERROR, 'unable to connect to internal OpenID routes'); return { type: 'application/json', body: result.body }; + } else if (location === 'carddav') { + const domainObject = await domains.get(domain); + if (!domainObject) throw new BoxError(BoxError.NOT_FOUND, 'Domain not found'); + if (!domainObject.wellKnown || !domainObject.wellKnown.carddav) throw new BoxError(BoxError.NOT_FOUND, 'No custom well-known config'); + + return { redirectTo: domainObject.wellKnown.carddav }; + } else if (location === 'caldav') { + const domainObject = await domains.get(domain); + if (!domainObject) throw new BoxError(BoxError.NOT_FOUND, 'Domain not found'); + if (!domainObject.wellKnown || !domainObject.wellKnown.caldav) throw new BoxError(BoxError.NOT_FOUND, 'No custom well-known config'); + + return { redirectTo: domainObject.wellKnown.caldav }; } else { throw new BoxError(BoxError.NOT_FOUND, 'No custom well-known config'); }