From 3078b9f4c2f0348fdd02373c6d028753b5fc9c29 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Mon, 26 Jan 2026 20:37:14 +0100 Subject: [PATCH 1/3] add Hub CE registration form --- assets/js/hubce.js | 99 +++++++++++++++++ content/hub-register.de.html | 5 + content/hub-register.en.html | 5 + i18n/en.yaml | 29 +++++ layouts/hub-register/single.html | 175 +++++++++++++++++++++++++++++++ 5 files changed, 313 insertions(+) create mode 100644 assets/js/hubce.js create mode 100644 content/hub-register.de.html create mode 100644 content/hub-register.en.html create mode 100644 layouts/hub-register/single.html diff --git a/assets/js/hubce.js b/assets/js/hubce.js new file mode 100644 index 000000000..b0c15bacc --- /dev/null +++ b/assets/js/hubce.js @@ -0,0 +1,99 @@ +"use strict"; + +// requires newsletter.js +const VERIFY_EMAIL_URL = API_BASE_URL + '/connect/email/verify'; +const GET_LICENSE_URL = API_BASE_URL + '/licenses/hub'; + +class HubCE { + + constructor(form, feedbackData, submitData, searchParams) { + this._form = form; + this._feedbackData = feedbackData; + this._submitData = submitData; + this._searchParams = searchParams; + this._submitData.hubId = searchParams.get('hubId'); + + // continue after email verified: + if (searchParams.get('verifiedEmail')) { + feedbackData.currentStep = 2; + feedbackData.success = true; + this.getHubLicense(); + } + } + + validateEmail() { + if (!$(this._form)[0].checkValidity()) { + $(this._form).find(':input').addClass('show-invalid'); + this._feedbackData.errorMessage = 'Please fill in all required fields.'; + return; + } + this.onValidationSucceeded(); + } + + onValidationFailed(error) { + this._feedbackData.inProgress = false; + this._feedbackData.errorMessage = error; + } + + onValidationSucceeded() { + this._feedbackData.currentStep++; + this._feedbackData.inProgress = false; + this._feedbackData.errorMessage = ''; + } + + sendConfirmationEmail() { + if (!$(this._form)[0].checkValidity()) { + $(this._form).find(':input').addClass('show-invalid'); + this._feedbackData.errorMessage = 'Please fill in all required fields.'; + return; + } + + this._feedbackData.success = false; + this._feedbackData.inProgress = true; + this._feedbackData.errorMessage = ''; + $.ajax({ + url: VERIFY_EMAIL_URL, + type: 'POST', + data: { + email: this._submitData.email, + hubId: this._submitData.hubId, + verifyCaptcha: this._submitData.captcha, + verifyEmail: this._submitData.email, + verifyTarget: 'registerhubce' + } + }).done(_ => { + this.onRequestSucceeded(); + if (this._submitData.acceptNewsletter) { + subscribeToNewsletter(this._submitData.email, 7); // FIXME move to backend + } + }).fail(xhr => { + this.onRequestFailed(xhr.responseJSON?.message || 'Sending confirmation email failed.'); + }); + } + + getHubLicense() { + $.ajax({ + url: GET_LICENSE_URL, + type: 'GET', + data: { + hubId: this._submitData.hubId + } + }).done(response => { + this._feedbackData.licenseText = response; + }).fail(xhr => { + this.onRequestFailed(xhr.responseJSON?.message || 'Fetching license failed.'); + }); + } + + onRequestFailed(error) { + this._feedbackData.inProgress = false; + this._feedbackData.errorMessage = error; + } + + onRequestSucceeded() { + this._feedbackData.currentStep++; + this._feedbackData.inProgress = false; + this._feedbackData.errorMessage = ''; + } + +} \ No newline at end of file diff --git a/content/hub-register.de.html b/content/hub-register.de.html new file mode 100644 index 000000000..4ae0011e9 --- /dev/null +++ b/content/hub-register.de.html @@ -0,0 +1,5 @@ +--- +title: "Cryptomator Hub: Registrieren" +url: "/de/hub/register" +type: "hub-register" +--- diff --git a/content/hub-register.en.html b/content/hub-register.en.html new file mode 100644 index 000000000..4e610fdb1 --- /dev/null +++ b/content/hub-register.en.html @@ -0,0 +1,5 @@ +--- +title: "Cryptomator Hub: Register" +url: "/hub/register" +type: "hub-register" +--- diff --git a/i18n/en.yaml b/i18n/en.yaml index ddbc6b247..86e5eecde 100644 --- a/i18n/en.yaml +++ b/i18n/en.yaml @@ -659,6 +659,35 @@ - id: hub_demo_contact_us_button translation: "Contact Us" +# Hub CE Registration +- id: hub_ce_registration_description + translation: "Register your Cryptomator Hub instance for a free Community Edition license." + +- id: hub_ce_registration_steps_title + translation: "Step of " +- id: hub_ce_registration_steps_next + translation: "Next" + +- id: hub_ce_registration_step_1_nav_title + translation: "Email Address" +- id: hub_ce_registration_step_1_title + translation: "What's your email address?" +- id: hub_ce_registration_step_1_email_placeholder + translation: "Email address" + +- id: hub_ce_registration_step_2_confirmation_nav_title + translation: "Confirmation" +- id: hub_ce_registration_step_2_confirmation_title + translation: "Please confirm your email address" +- id: hub_ce_registration_step_2_instructions + translation: "We are going to send a confirmation email to " + +- id: hub_ce_registration_step_3_license_nav_title + translation: "License Key" +- id: hub_ce_registration_step_3_license_title + translation: "Your Community Edition License Key" + + # Hub Managed - id: hub_managed_description translation: "Request access to a managed instance of Cryptomator Hub and get your team on board with client-side encryption for your cloud storage." diff --git a/layouts/hub-register/single.html b/layouts/hub-register/single.html new file mode 100644 index 000000000..880a40226 --- /dev/null +++ b/layouts/hub-register/single.html @@ -0,0 +1,175 @@ +{{ define "preloads" }} + {{ partial "altcha-css.html" . }} +{{ end }} +{{ define "main" }} +
+
+

{{ .Title }}

+

{{ i18n "hub_ce_registration_description" }}

+
+ +
+
+
+ +
+ + + + + + + + + + + + +
+
+
+{{ end }} +{{ define "script" }} + {{ if hugo.IsDevelopment }} + {{ $newsletterJs := resources.Get "js/newsletter.js" }} + + {{ $hubCeJs := resources.Get "js/hubce.js" }} + + {{ $altchaJs := resources.Get "js/altcha/altcha.js" }} + + {{ $altchaWorkerJs := resources.Get "js/altcha/worker.js" }} + + {{ else }} + {{ $newsletterJs := resources.Get "js/newsletter.js" | minify | fingerprint }} + + {{ $hubCeJs := resources.Get "js/hubce.js" | minify | fingerprint }} + + {{ $altchaJs := resources.Get "js/altcha/altcha.js" | minify | fingerprint }} + + {{ $altchaWorkerJs := resources.Get "js/altcha/worker.js" }} + + {{ end }} +{{ end }} From 4054f2b5c0384832ebb188f03f751bacae4f2756 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 28 Jan 2026 14:59:50 +0100 Subject: [PATCH 2/3] =?UTF-8?q?`GET=20/licenses/hub`=20=E2=86=92=20`POST?= =?UTF-8?q?=20/licenses/hub/prod`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/js/hubce.js | 18 +++-- layouts/hub-register/single.html | 111 +++++++++++++++++-------------- 2 files changed, 76 insertions(+), 53 deletions(-) diff --git a/assets/js/hubce.js b/assets/js/hubce.js index b0c15bacc..d56a1922e 100644 --- a/assets/js/hubce.js +++ b/assets/js/hubce.js @@ -2,7 +2,7 @@ // requires newsletter.js const VERIFY_EMAIL_URL = API_BASE_URL + '/connect/email/verify'; -const GET_LICENSE_URL = API_BASE_URL + '/licenses/hub'; +const CLAIM_LICENSE_URL = API_BASE_URL + '/licenses/hub/prod'; class HubCE { @@ -17,6 +17,15 @@ class HubCE { if (searchParams.get('verifiedEmail')) { feedbackData.currentStep = 2; feedbackData.success = true; + } + } + + submit() { + if (this._feedbackData.currentStep === 0) { + this.validateEmail(); + } else if (this._feedbackData.currentStep === 1) { + this.sendConfirmationEmail(); + } else if (this._feedbackData.currentStep === 2) { this.getHubLicense(); } } @@ -73,10 +82,11 @@ class HubCE { getHubLicense() { $.ajax({ - url: GET_LICENSE_URL, - type: 'GET', + url: CLAIM_LICENSE_URL, + type: 'POST', data: { - hubId: this._submitData.hubId + hubId: this._submitData.hubId, + captcha: this._submitData.captcha } }).done(response => { this._feedbackData.licenseText = response; diff --git a/layouts/hub-register/single.html b/layouts/hub-register/single.html index 880a40226..551b1ba18 100644 --- a/layouts/hub-register/single.html +++ b/layouts/hub-register/single.html @@ -8,59 +8,70 @@

{{ .Title }}

{{ i18n "hub_ce_registration_description" }}

-
-
-
- +
+ - + - + -
-
+ + {{ end }} {{ define "script" }} From d0e488ebdd93f5af330fc2d76a3077b0aec2638a Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Thu, 29 Jan 2026 13:26:03 +0100 Subject: [PATCH 3/3] pass `#oldLicense=...` to license refresh endpoint --- assets/js/hubce.js | 11 +++++------ layouts/hub-register/single.html | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/assets/js/hubce.js b/assets/js/hubce.js index d56a1922e..d8b042693 100644 --- a/assets/js/hubce.js +++ b/assets/js/hubce.js @@ -2,7 +2,7 @@ // requires newsletter.js const VERIFY_EMAIL_URL = API_BASE_URL + '/connect/email/verify'; -const CLAIM_LICENSE_URL = API_BASE_URL + '/licenses/hub/prod'; +const REFRESH_LICENSE_URL = API_BASE_URL + '/licenses/hub/refresh'; class HubCE { @@ -11,7 +11,7 @@ class HubCE { this._feedbackData = feedbackData; this._submitData = submitData; this._searchParams = searchParams; - this._submitData.hubId = searchParams.get('hubId'); + this._submitData.oldLicense = searchParams.get('oldLicense'); // continue after email verified: if (searchParams.get('verifiedEmail')) { @@ -65,7 +65,7 @@ class HubCE { type: 'POST', data: { email: this._submitData.email, - hubId: this._submitData.hubId, + oldLicense: this._submitData.oldLicense, verifyCaptcha: this._submitData.captcha, verifyEmail: this._submitData.email, verifyTarget: 'registerhubce' @@ -82,11 +82,10 @@ class HubCE { getHubLicense() { $.ajax({ - url: CLAIM_LICENSE_URL, + url: REFRESH_LICENSE_URL, type: 'POST', data: { - hubId: this._submitData.hubId, - captcha: this._submitData.captcha + token: this._submitData.oldLicense } }).done(response => { this._feedbackData.licenseText = response; diff --git a/layouts/hub-register/single.html b/layouts/hub-register/single.html index 551b1ba18..192bf37d7 100644 --- a/layouts/hub-register/single.html +++ b/layouts/hub-register/single.html @@ -2,7 +2,7 @@ {{ partial "altcha-css.html" . }} {{ end }} {{ define "main" }} -
+

{{ .Title }}

{{ i18n "hub_ce_registration_description" }}

@@ -82,7 +82,7 @@

-