✨(frontend) add a button and modal to create maildomains (#313)

* ✨(feat) create modal, serializer and add button

* ✨(frontend) refetch on domain creation

* 🚨(frontend) fix linter

* ✅(backend) add domain creation test

* ✨(frontend) add toaster for domain creation

* 💬(frontend) add translation and fix small typo

* ✨(front+back) add custom_attributes on domain creation

* 💄(frontend) add style for create domain modal

* 💬(frontend) add missing translations + add end of file line breaks

* 🎨(frontend) move toaster to admin layout

* 🦺(frontend) validate domain name in frontend

* 💄(frontend) remove unused css

* ✅(backend) add more tests

* 🎨(backend) improve maildomain structure

* 🎨(frontend) follow nitpicks
This commit is contained in:
Stanislas Bruhière
2025-09-02 20:13:11 +02:00
committed by GitHub
parent 38439b95ce
commit 02bce211ea
15 changed files with 645 additions and 6 deletions
+113
View File
@@ -2370,6 +2370,45 @@
"description": ""
}
}
},
"post": {
"operationId": "maildomains_create",
"description": "ViewSet for listing MailDomains the user administers.\nProvides a top-level entry for mail domain administration.\nEndpoint: /maildomains/",
"tags": [
"maildomains"
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailDomainAdminWriteRequest"
}
},
"multipart/form-data": {
"schema": {
"$ref": "#/components/schemas/MailDomainAdminWriteRequest"
}
}
},
"required": true
},
"security": [
{
"cookieAuth": []
}
],
"responses": {
"201": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailDomainAdminWrite"
}
}
},
"description": ""
}
}
}
},
"/api/v1.0/maildomains/{maildomain_pk}/mailboxes/": {
@@ -4336,6 +4375,80 @@
"updated_at"
]
},
"MailDomainAdminWrite": {
"type": "object",
"description": "Serialize mail domains for creating / editing admin view.",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"readOnly": true,
"description": "primary key for the record as UUID"
},
"name": {
"type": "string",
"pattern": "^[a-z0-9][a-z0-9.-]*[a-z0-9]$",
"maxLength": 253
},
"created_at": {
"type": "string",
"format": "date-time",
"readOnly": true,
"title": "Created on",
"description": "date and time at which a record was created"
},
"updated_at": {
"type": "string",
"format": "date-time",
"readOnly": true,
"title": "Updated on",
"description": "date and time at which a record was last updated"
},
"oidc_autojoin": {
"type": "boolean",
"description": "Create mailboxes automatically based on OIDC emails."
},
"identity_sync": {
"type": "boolean",
"description": "Sync mailboxes to an identity provider."
},
"custom_attributes": {
"description": "Metadata to sync to the maildomain group in the identity provider."
}
},
"required": [
"created_at",
"id",
"name",
"updated_at"
]
},
"MailDomainAdminWriteRequest": {
"type": "object",
"description": "Serialize mail domains for creating / editing admin view.",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"pattern": "^[a-z0-9][a-z0-9.-]*[a-z0-9]$",
"maxLength": 253
},
"oidc_autojoin": {
"type": "boolean",
"description": "Create mailboxes automatically based on OIDC emails."
},
"identity_sync": {
"type": "boolean",
"description": "Sync mailboxes to an identity provider."
},
"custom_attributes": {
"description": "Metadata to sync to the maildomain group in the identity provider."
}
},
"required": [
"name"
]
},
"Mailbox": {
"type": "object",
"description": "Serialize mailboxes.",
+7
View File
@@ -808,6 +808,13 @@ class MailDomainAdminSerializer(AbilitiesModelSerializer):
"""Return the abilities for the mail domain."""
return super().get_abilities(instance)
class MailDomainAdminWriteSerializer(serializers.ModelSerializer):
"""Serialize mail domains for creating / editing admin view."""
class Meta:
model = models.MailDomain
fields = ["id", "name", "created_at", "updated_at", "oidc_autojoin", "identity_sync", "custom_attributes"]
read_only_fields = ["id", "created_at", "updated_at"]
class MailboxAccessNestedUserSerializer(serializers.ModelSerializer):
"""
+12 -1
View File
@@ -35,7 +35,7 @@ from core.services.identity.keycloak import reset_keycloak_user_password
class AdminMailDomainViewSet(
mixins.ListModelMixin, viewsets.GenericViewSet, mixins.RetrieveModelMixin
mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet
):
"""
ViewSet for listing MailDomains the user administers.
@@ -48,6 +48,17 @@ class AdminMailDomainViewSet(
core_permissions.IsSuperUser | core_permissions.IsMailDomainAdmin
]
def get_permissions(self):
if self.action == "create":
return [core_permissions.IsSuperUser()]
return super().get_permissions()
def get_serializer_class(self):
"""Select serializer based on action."""
if self.action == "create":
return core_serializers.MailDomainAdminWriteSerializer
return super().get_serializer_class()
def get_queryset(self):
user = self.request.user
if not user or not user.is_authenticated: