From ba30b1d3eec73718add6585f30c6b7959cb21850 Mon Sep 17 00:00:00 2001 From: Marie PUPO JEAMMET Date: Fri, 30 Aug 2024 15:49:04 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=97=83=EF=B8=8F(models)=20remove=20'secre?= =?UTF-8?q?t'=20field=20from=20mailbox=20model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We remove 'secret' field, as it won't be of use in interactions between la Régie and dimail. Régie credentials will be stored and used as project variable. --- CHANGELOG.md | 8 ++++++-- .../migrations/0013_remove_maildomain_secret.py | 17 +++++++++++++++++ src/backend/mailbox_manager/models.py | 11 +++++++---- src/backend/mailbox_manager/utils/dimail.py | 14 ++++++++------ src/backend/people/settings.py | 10 +++++++++- 5 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 src/backend/mailbox_manager/migrations/0013_remove_maildomain_secret.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ab90db..3f4f8d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,11 +13,15 @@ and this project adheres to - 📈(monitoring) configure sentry monitoring #378 - 🥅(frontend) improve api error handling #355 +### Changed + +- 🗃️(models) move dimail 'secret' to settings #372 + ### Fixed - 🐛(dimail) improve handling of dimail errors on failed mailbox creation #377 -- 💬(frontend) fix group member removal text #382 -- 💬(frontend) fix add mail domain text #382 +- 💬(frontend) fix group member removal text #382 +- 💬(frontend) fix add mail domain text #382 - 🐛(frontend) fix keyboard navigation #379 - 🐛(frontend) fix add mail domain form submission #355 diff --git a/src/backend/mailbox_manager/migrations/0013_remove_maildomain_secret.py b/src/backend/mailbox_manager/migrations/0013_remove_maildomain_secret.py new file mode 100644 index 0000000..34fa5bf --- /dev/null +++ b/src/backend/mailbox_manager/migrations/0013_remove_maildomain_secret.py @@ -0,0 +1,17 @@ +# Generated by Django 5.1 on 2024-08-30 12:46 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mailbox_manager', '0012_alter_mailbox_local_part'), + ] + + operations = [ + migrations.RemoveField( + model_name='maildomain', + name='secret', + ), + ] diff --git a/src/backend/mailbox_manager/models.py b/src/backend/mailbox_manager/models.py index 1933b50..882244c 100644 --- a/src/backend/mailbox_manager/models.py +++ b/src/backend/mailbox_manager/models.py @@ -26,7 +26,6 @@ class MailDomain(BaseModel): default=MailDomainStatusChoices.PENDING, choices=MailDomainStatusChoices.choices, ) - secret = models.CharField(_("secret"), max_length=255, null=True, blank=True) class Meta: db_table = "people_mail_domain" @@ -139,15 +138,19 @@ class Mailbox(BaseModel): return f"{self.local_part!s}@{self.domain.name:s}" def clean(self): - """Mailboxes can be created only on enabled domains, with a set secret.""" + """ + Mailboxes can only be created on enabled domains. + Also, mail-provisioning API credentials must be set for dimail to allow auth. + """ if self.domain.status != MailDomainStatusChoices.ENABLED: raise exceptions.ValidationError( "You can create mailbox only for a domain enabled" ) - if not self.domain.secret: + # Won't be able to query user token if MAIL_PROVISIONING_API_CREDENTIALS are not set + if not settings.MAIL_PROVISIONING_API_CREDENTIALS: raise exceptions.ValidationError( - "Please configure your domain's secret before creating any mailbox." + "Please configure MAIL_PROVISIONING_API_CREDENTIALS before creating any mailbox." ) def save(self, *args, **kwargs): diff --git a/src/backend/mailbox_manager/utils/dimail.py b/src/backend/mailbox_manager/utils/dimail.py index 3aaa595..9bd8d13 100644 --- a/src/backend/mailbox_manager/utils/dimail.py +++ b/src/backend/mailbox_manager/utils/dimail.py @@ -30,14 +30,16 @@ class DimailAPIClient: API_URL = settings.MAIL_PROVISIONING_API_URL - def get_headers(self, domain): + def get_headers(self): """Build header dict from domain object.""" # self.secret is the encoded basic auth, to request a new token from dimail-api headers = {"Content-Type": "application/json"} response = requests.get( f"{self.API_URL}/token/", - headers={"Authorization": f"Basic {domain.secret}"}, + headers={ + "Authorization": f"Basic {settings.MAIL_PROVISIONING_API_CREDENTIALS}" + }, timeout=20, ) @@ -48,8 +50,8 @@ class DimailAPIClient: if response.status_code == status.HTTP_403_FORBIDDEN: logger.error( - "[DIMAIL] 403 Forbidden: please check the mail domain secret of %s", - domain.name, + "[DIMAIL] 403 Forbidden: Could not retrieve a token,\ + please check 'MAIL_PROVISIONING_API_CREDENTIALS' setting.", ) raise exceptions.PermissionDenied @@ -68,7 +70,7 @@ class DimailAPIClient: response = session.post( f"{self.API_URL}/domains/{mailbox.domain}/mailboxes/{mailbox.local_part}/", json=payload, - headers=self.get_headers(mailbox.domain), + headers=self.get_headers(), verify=True, timeout=10, ) @@ -98,7 +100,7 @@ class DimailAPIClient: if response.status_code == status.HTTP_403_FORBIDDEN: raise exceptions.PermissionDenied( - f"Secret not valid for this domain {mailbox.domain.name}" + "Permission denied. Please check your MAIL_PROVISIONING_API_CREDENTIALS." ) return self.pass_dimail_unexpected_response(response) diff --git a/src/backend/people/settings.py b/src/backend/people/settings.py index 8ba2f46..b5ee319 100755 --- a/src/backend/people/settings.py +++ b/src/backend/people/settings.py @@ -415,12 +415,17 @@ class Base(Configuration): OIDC_TIMEOUT = values.Value(None, environ_name="OIDC_TIMEOUT", environ_prefix=None) - # mailboxes provisioning API + # MAILBOX-PROVISIONING API MAIL_PROVISIONING_API_URL = values.Value( default="https://api.dev.ox.numerique.gouv.fr", environ_name="MAIL_PROVISIONING_API_URL", environ_prefix=None, ) + MAIL_PROVISIONING_API_CREDENTIALS = values.Value( + default=None, + environ_name="MAIL_PROVISIONING_API_CREDENTIALS", + environ_prefix=None, + ) FEATURES = { "TEAMS": values.BooleanValue( @@ -575,6 +580,9 @@ class Test(Base): CELERY_TASK_ALWAYS_EAGER = values.BooleanValue(True) + # this is a dev credentials for mail provisioning API + MAIL_PROVISIONING_API_CREDENTIALS = "bGFfcmVnaWU6cGFzc3dvcmQ" + class ContinuousIntegration(Test): """