diff --git a/frontend/src/api/accounts.js b/frontend/src/api/accounts.js index c04b97ce5..f0e4902cf 100644 --- a/frontend/src/api/accounts.js +++ b/frontend/src/api/accounts.js @@ -17,6 +17,9 @@ export default { getRandomPassword() { return repository.get(`${resource}/random_password/`) }, + getCredentials(accountId) { + return repository.get(`credentials/${accountId}/`, { responseType: 'blob' }) + }, validate(data) { return repository.post(`${resource}/validate/`, data) }, diff --git a/frontend/src/components/admin/identities/IdentityList.vue b/frontend/src/components/admin/identities/IdentityList.vue index fcb23d18c..1591bc92a 100644 --- a/frontend/src/components/admin/identities/IdentityList.vue +++ b/frontend/src/components/admin/identities/IdentityList.vue @@ -362,9 +362,9 @@ function getMenuItems(item) { result.push({ label: element.label, icon: element.icon, - onClick: () => { - if (element.type === 'download') { - //TODO : downloadFile(element) + onClick: (account) => { + if (element.name === 'get_credentials') { + downloadCredentials(account) } fetchIdentities() }, @@ -438,6 +438,16 @@ async function deleteAccount(account) { } } +async function downloadCredentials(account) { + const resp = await accountsApi.getCredentials(account.pk) + const blob = new Blob([resp.data], { type: resp.headers['Content-Type'] }) + const link = document.createElement('a') + link.href = URL.createObjectURL(blob) + link.download = `credentials_${account.pk}.pdf` + link.click() + URL.revokeObjectURL(link.href) +} + function editAlias() {} function deleteIdentities() {} diff --git a/modoboa/pdfcredentials/api/v2/serializers.py b/modoboa/pdfcredentials/api/v2/serializers.py index 502657b08..49d0625b4 100644 --- a/modoboa/pdfcredentials/api/v2/serializers.py +++ b/modoboa/pdfcredentials/api/v2/serializers.py @@ -38,12 +38,16 @@ class PDFCredentialsSettingsSerializer(serializers.Serializer): required=False, allow_blank=True, allow_null=True ) include_connection_settings = serializers.BooleanField(default=False) - smtp_server_address = serializers.CharField() + smtp_server_address = serializers.CharField( + required=False, allow_blank=True, allow_null=True + ) smtp_server_port = serializers.IntegerField(default=587) smtp_connection_security = serializers.ChoiceField( choices=CONNECTION_SECURITY_MODES, default="starttls" ) - imap_server_address = serializers.CharField() + imap_server_address = serializers.CharField( + required=False, allow_blank=True, allow_null=True + ) imap_server_port = serializers.IntegerField(default=143) imap_connection_security = serializers.ChoiceField( choices=CONNECTION_SECURITY_MODES, default="starttls" @@ -72,13 +76,21 @@ class PDFCredentialsSettingsSerializer(serializers.Serializer): enabled_pdfcredentials is None and param_tools.get_global_parameter("enabled_pdfcredentials") ) + errors = {} if condition: storage_dir = data.get("storage_dir", None) if storage_dir is not None: if not os.path.isdir(storage_dir): - raise serializers.ValidationError(_("Directory not found.")) - if not os.access(storage_dir, os.W_OK): - raise serializers.ValidationError(_("Directory is not writable")) + errors["storage_dir"] = _("Directory not found.") + elif not os.access(storage_dir, os.W_OK): + errors["storage_dir"] = _("Directory is not writable") + include_connection_settings = data.get("include_connection_settings") + if include_connection_settings: + for field in ["smtp_server_address", "imap_server_address"]: + if not data.get(field): + errors[field] = _("This field is required.") + if errors: + raise serializers.ValidationError(errors) return data diff --git a/modoboa/pdfcredentials/api/v2/tests.py b/modoboa/pdfcredentials/api/v2/tests.py index f0ac8a2dd..ac121f451 100644 --- a/modoboa/pdfcredentials/api/v2/tests.py +++ b/modoboa/pdfcredentials/api/v2/tests.py @@ -190,3 +190,31 @@ class PDFCredentialViewTestCase(ModoAPITestCase): data["enabled_pdfcredentials"] = False resp = self.client.put(url, data, format="json") self.assertEqual(resp.status_code, 200) + + def test_optional_settings(self): + url = reverse("v2:parameter-global-detail", args=["pdfcredentials"]) + path = f"{self.workdir}/credentials" + os.makedirs(path) + data = { + "enabled_pdfcredentials": True, + "storage_dir": path, + "webpanel_url": "http://localhost", + } + resp = self.client.put(url, data, format="json") + self.assertEqual(resp.status_code, 200) + + data["include_connection_settings"] = True + resp = self.client.put(url, data, format="json") + self.assertEqual(resp.status_code, 400) + errors = resp.json() + self.assertEqual(errors["smtp_server_address"][0], "This field is required.") + self.assertEqual(errors["imap_server_address"][0], "This field is required.") + + data.update( + { + "smtp_server_address": "mail.localhost", + "imap_server_address": "mail.localhost", + } + ) + resp = self.client.put(url, data, format="json") + self.assertEqual(resp.status_code, 200) diff --git a/modoboa/pdfcredentials/app_settings.py b/modoboa/pdfcredentials/app_settings.py index 4f2efeade..ea54d6405 100644 --- a/modoboa/pdfcredentials/app_settings.py +++ b/modoboa/pdfcredentials/app_settings.py @@ -121,7 +121,7 @@ PDF_CREDENTIALS_PARAMETERS_STRUCT = collections.OrderedDict( "smtp_server_address", { "label": _("SMTP server address"), - "display": "include_connection_settings=True", + "display": "include_connection_settings=true", "help_text": _( "Address of the SMTP server (hostname or IP)" ),