Files
messages/docs/model-custom-attributes.md
jbpenrath f68925b8bd (frontend) render fields according to SCHEMA_CUSTOM_ATTRIBUTES_USER
In the personal mailbox form, we now render extra fields according to the
`SCHEMA_CUSTOM_ATTRIBUTES_USER` got through config endpoint.

Those fields are validated through zod and the schema is generated through
`zod-from-json-schema` package. Then a custom component is in charge to
render the right component according to the schema property `type`.
2025-08-06 10:12:36 +02:00

4.1 KiB

Model Custom Attributes

Purpose

The User and MailDomain models support storing additional data via a custom_attributes JSON field. If an identity provider is configured, these attributes are also synchronized with it.

🗒️ Note This feature allows you to extend the core models without altering the database schema.


Usage

For each model, the structure of the custom_attributes data can be defined via environment variables. This enables customization of your Messages instance without forking the project.

The value must be a valid JSON Schema string following the 2020-12 specification.

💡 Tip Before deploying your application, lint your JSON Schema to ensure it is correctly formatted. Several tools are available.

⚠️ Warning Altering schemas could require to you to migrate your data! Modify it with caution.


Schema Structure

Custom attributes must be an object with only primitive properties (string, number, integer or boolean).

Example of a valid JSON Schema:

  • job_title: a string with a minimum length of 3 characters.
  • is_elected: a boolean that defaults to false.
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/suitenumerique/messages/schemas/custom-fields/user",
  "type": "object",
  "title": "User custom fields",
  "additionalProperties": false,
  "properties": {
    "job_title": {
      "type": "string",
      "title": "Job title",
      "default": "",
      "description": "The job name of the user",
      "minLength": 3,
      "x-i18n": {
        "title": {
          "fr": "Fonction",
          "en": "Job title"
        },
        "description": {
          "fr": "Le nom de la fonction de l'utilisateur",
          "en": "The job name of the user"
        }
      }
    },
    "is_elected": {
      "type": "boolean",
      "title": "Is elected",
      "default": false,
      "description": "Whether the user is elected",
      "x-i18n": {
        "title": {
          "fr": "Est élu",
          "en": "Is elected"
        },
        "description": {
          "fr": "Indique si l'utilisateur est élu"
        }
      }
    }
  },
  "required": []
}

Internationalization

If your application is not internationalized, you can skip this section. Providing a title and description for each property is sufficient.

In the example above, we use a custom annotation named x-i18n. This property allows defining localized title and description values for each property in the supported languages.

🗒️ Note The x-i18n object is optional. If omitted, the values in title and description will be used as-is.


Data Validation

The custom attributes schema is used to:

  • Render input fields and validate data on the frontend.
  • Validate data on the backend.

Frontend

  • Schema generation: We use zod-from-json-schema to generate a Zod schema. This library provides broad (but partial) support for the 2020-12 specification.

  • Form rendering: The custom component RhfJsonSchemaField chooses the correct input to render based on the property type.

  • Form state: Managed by React Hook Form, in line with other forms in the application.

⚠️ Warning Because zod-from-json-schema support for 2020-12 is partial, certain advanced JSON Schema features may not work as expected on the frontend. Always test your schema in the UI before deploying.


Backend

We use the jsonschema package for validation. It provides full support for the 2020-12 specification, ensuring data integrity even if frontend validation is bypassed.