refac: DELETE /v1/user/{id}?expected_role_id=N, user.remove audit event, 409 target_role_not_found, GetAll returns its error, Own-scope visibility filter moved into repos, JSON tags removed from use-case types

This commit is contained in:
Florian Sylvain committed 2026-10-29 16:28:25 +01:00
1 parent 5d6f378fce
commit b39a41be88
124 files changed
+8816 -523

No files matched your search

+122 -36
View File
@@ -590,8 +590,6 @@ export const messages = {
"There's already a pending invite for this address.":
'Une invitation est déjà en attente pour cette adresse.',
'This address already has an account.': 'Cette adresse a déjà un compte.',
"Couldn't send the invite. Try again in a moment.":
'Impossible d’envoyer l’invitation. Réessayez dans un instant.',
'Loading users': 'Chargement des utilisateurs',
"Couldn't load users": 'Impossible de charger les utilisateurs',
Name: 'Nom',
@@ -928,7 +926,6 @@ export const messages = {
Public: 'Public',
'Verified user': 'Utilisateur vérifié',
'Owner only': 'Propriétaire uniquement',
'Owner or admin': 'Propriétaire ou administrateur',
'Settings · owner only': 'Paramètres · propriétaire uniquement',
'Activity log': 'Journal d’activité',
Authentication: 'Authentification',
@@ -958,8 +955,6 @@ export const messages = {
'Aucune clé nécessaire. Deux routes en lecture seule, et seuls les articles publiés sont renvoyés.',
'API key': 'Clé d’API',
'Full access': 'Accès complet',
"Send `Authorization: Bearer rcms_…`. Requests act as the user who created the key, with that user's role (owner or admin). A key never has more rights than its creator.":
'Envoyez `Authorization: Bearer rcms_…`. Les requêtes agissent comme la personne qui a créé la clé, avec son rôle (propriétaire ou administrateur). Une clé n’a jamais plus de droits que son créateur.',
'Keys start with `rcms_` and are shown in full once, when you create them.':
'Les clés commencent par `rcms_` et ne sont affichées en entier qu’une fois, à leur création.',
'A key can\'t create, list or revoke API keys, verify or cancel a registration, or call anything under `/v1/system`. Those routes answer 403 "This action needs a real session." An invalid, unknown, expired or revoked key answers 401, even on public routes, and so does a key whose user was deleted or unverified. Routes that need a permission answer 403 "missing_permission" to a key when the role of its creator does not hold it.':
@@ -1657,12 +1652,6 @@ export const messages = {
'Delete an image. Articles that use it show a broken image.':
'Supprime une image. Les articles qui l’utilisent affichent une image cassée.',
'Merge identical copies into one image.': 'Fusionne les copies identiques en une seule image.',
'Get the automatic duplicate purge settings.':
'Récupère les paramètres de la purge automatique des doublons.',
'Turn the automatic purge on or off, or change its interval.':
'Active ou désactive la purge automatique, ou modifie son intervalle.',
'Preview what a purge would merge. Nothing changes.':
'Prévisualise ce qu’une purge fusionnerait. Rien n’est modifié.',
'Merge every group of identical copies. Send the preview fingerprint to refuse a changed library.':
'Fusionne chaque groupe de copies identiques. Envoyez l’empreinte de l’aperçu pour refuser une médiathèque modifiée.',
'List users and invites.': 'Liste les utilisateurs et les invitations.',
@@ -2244,8 +2233,6 @@ export const messages = {
'Liste les adresses publiées d’un site, par identifiant croissant, sous forme de tableau de { url, modified_at, noindex }. Le total est dans l’en-tête X-Total-Count.',
'The sites an article can belong to. Any verified user can read them; changes are made in the browser by the owner.':
'Les sites auxquels un article peut appartenir. Tout utilisateur vérifié peut les lire ; les modifications se font dans le navigateur par le propriétaire.',
'Site SEO defaults are owner only. Article SEO fields need only the right to edit the article.':
'Les valeurs SEO par défaut d’un site sont réservées au propriétaire. Les champs SEO d’un article demandent seulement le droit de modifier l’article.',
'The server expects the ID to be in the format of an unsigned 32-bit integer (uint32).':
'Le serveur attend un identifiant au format d’un entier non signé de 32 bits (uint32).',
'Article not found': 'Article introuvable',
@@ -2742,8 +2729,6 @@ export const messages = {
'Status codes and messages': 'Codes d’état et messages',
'Images, CORS and ?format=': 'Images, CORS et ?format=',
'{0} routes, not available to API keys': '{0} routes, indisponibles avec une clé API',
'Define your own kind of content, like events or recipes. An owner or admin creates a type made of 1 to 50 ordered fields; the type then has its own entry routes.':
'Définissez votre propre type de contenu, comme des événements ou des recettes. Un propriétaire ou un administrateur crée un type composé de 1 à 50 champs ordonnés ; le type a alors ses propres routes d’entrées.',
'A content type has a `key` (2 to 40 lowercase letters, digits or hyphens, chosen at creation and never changed) and fields. Each field has a `key` (letters, digits and underscores, starting with a letter), a `label`, a `type` and rules.':
'Un type de contenu a une `key` (2 à 40 lettres minuscules, chiffres ou tirets, choisie à la création et jamais modifiée) et des champs. Chaque champ a une `key` (lettres, chiffres et tirets bas, commençant par une lettre), un `label`, un `type` et des règles.',
'Field object': 'Objet champ',
@@ -2767,21 +2752,14 @@ export const messages = {
'identifiants d’entrées d’un autre type de contenu ; `relation: { content_type, kind }`, kind valant one_to_one | one_to_many | many_to_many',
'List all custom content types.': 'Liste tous les types de contenu personnalisés.',
'Get one content type with its fields.': 'Renvoie un type de contenu avec ses champs.',
'Create a content type.': 'Crée un type de contenu.',
"2 to 40 characters. Lowercase letters, digits and hyphens. Can't be changed later.":
'2 à 40 caractères. Lettres minuscules, chiffres et tirets. Ne peut pas être modifiée ensuite.',
'Up to 100 characters.': 'Jusqu’à 100 caractères.',
'Optional.': 'Facultatif.',
'1 to 50 fields, in order. See Field types.':
'1 à 50 champs, dans l’ordre. Voir Types de champ.',
"Replace the name, icon and fields of a type. The key never changes. Saved field keys and types can't change.":
'Remplace le nom, l’icône et les champs d’un type. La clé ne change jamais. Les clés et types des champs enregistrés ne peuvent pas changer.',
"Some existing entries don't fit the new fields. Nothing was changed.":
'Certaines entrées existantes ne conviennent pas aux nouveaux champs. Rien n’a été modifié.',
'Delete a content type. Only possible when it has no entries and no relation field points at it.':
'Supprime un type de contenu. Possible seulement s’il n’a aucune entrée et si aucun champ de relation ne pointe vers lui.',
'Read and write the content of a custom type. Any verified user can write entries.':
'Lisez et écrivez le contenu d’un type personnalisé. Tout utilisateur vérifié peut écrire des entrées.',
"An entry's `data` is an object keyed by field key, validated against the type. Responses add `media` (the resolved images for media fields, keyed by field key: id, filename, width, height, size and thumbnail_url, or { id, missing: true } if the image was deleted) and `relations` (the resolved first field of related entries).":
'Les `data` d’une entrée forment un objet indexé par clé de champ, validé selon le type. Les réponses ajoutent `media` (les images résolues des champs média, indexées par clé de champ : id, filename, width, height, size et thumbnail_url, ou { id, missing: true } si l’image a été supprimée) et `relations` (le premier champ résolu des entrées liées).',
'List entries of a type, one page at a time. The response is an object with items, total, page and size, not a bare array like articles.':
@@ -2799,12 +2777,6 @@ export const messages = {
'Les champs des articles, auteurs, sites, médias et utilisateurs, dans la même forme que les champs d’un type de contenu.',
'Built-in types are read-only: they cannot be changed through the API.':
'Les types intégrés sont en lecture seule : ils ne peuvent pas être modifiés par l’API.',
'List the built-in types (Articles, Authors, Sites, Media, Users) and their fields. Keys are article, author, site, media and user.':
'Liste les types intégrés (articles, auteurs, sites, médias, utilisateurs) et leurs champs. Les clés sont article, author, site, media et user.',
'Get one built-in type. Keys are article, author, site, media and user.':
'Renvoie un type intégré. Les clés sont article, author, site, media et user.',
'Merge every group of identical copies. Send the preview fingerprint to refuse a changed library. failed_groups counts groups that could not be purged; the others were still purged.':
'Fusionne chaque groupe de copies identiques. Envoyez l’empreinte de l’aperçu pour refuser une bibliothèque modifiée. failed_groups compte les groupes qui n’ont pas pu être purgés ; les autres l’ont été.',
'Sites and authors': 'Sites et auteurs',
'Read the sites and authors your content belongs to. Creating and changing them needs a session.':
'Lisez les sites et les auteurs auxquels votre contenu appartient. Les créer et les modifier demande une session.',
@@ -2998,7 +2970,6 @@ export const messages = {
'{0} saved changes to {1} at {2}. Reload to see them, or review how they differ from your edits.':
'{0} a enregistré des modifications sur {1} à {2}. Rechargez pour les voir, ou comparez-les à vos modifications.',
Someone: 'Quelqu’un',
"Couldn't save the role": 'Impossible d’enregistrer le rôle',
'{0} is updated for 1 member.': '{0} est mis à jour pour 1 membre.',
'{0} is updated for {1} members.': '{0} est mis à jour pour {1} membres.',
'Give the role a name.': 'Donnez un nom au rôle.',
@@ -3058,7 +3029,9 @@ export const messages = {
'edit activity retention': 'modifier la conservation de l’activité',
'transfer ownership': 'transférer la propriété',
'read any entry': 'lire n’importe quelle entrée',
'read only their own entries': 'lire uniquement leurs propres entrées',
'read online articles and their own drafts':
'lire les articles en ligne et leurs propres brouillons',
'read only entries they created': 'lire uniquement les entrées créées par la personne',
'create entries': 'créer des entrées',
'edit any entry': 'modifier n’importe quelle entrée',
'edit only their own': 'modifier uniquement les leurs',
@@ -3142,7 +3115,6 @@ export const messages = {
"A key can do what its creator's role can do, today. If the person's role changes, their keys change with it.":
'Une clé peut faire ce que le rôle de son créateur peut faire, aujourd’hui. Si le rôle de la personne change, ses clés changent avec lui.',
'A summary of your role, {0}. Read-only.': 'Un résumé de votre rôle, {0}. Lecture seule.',
'Assigned by {0}': 'Attribué par {0}',
'Change role': 'Changer le rôle',
'Change role for {0}': 'Changer le rôle de {0}',
'Changed the role of {0}': 'A changé le rôle de {0}',
@@ -3150,8 +3122,6 @@ export const messages = {
'Choose who becomes the owner. Only members can be chosen.':
'Choisissez qui devient propriétaire. Seuls les membres peuvent être choisis.',
Continue: 'Continuer',
"Couldn't change the role. Try again in a moment.":
'Impossible de changer le rôle. Réessayez dans un instant.',
"Couldn't transfer ownership. Try again in a moment.":
'Impossible de transférer la propriété. Réessayez dans un instant.',
'Failed to change the role of {0}': 'Échec du changement de rôle de {0}',
@@ -3165,7 +3135,6 @@ export const messages = {
'Moved the members of the role {0}': 'A déplacé les membres du rôle {0}',
'Only the owner can apply updates, delete a site and change activity retention.':
'Seul le propriétaire peut appliquer les mises à jour, supprimer un site et modifier la conservation de l’activité.',
'Ownership changed meanwhile': 'La propriété a changé entre-temps',
'Ownership transferred': 'Propriété transférée',
'Ownership transferred from {0} to {1}': 'Propriété transférée de {0} à {1}',
'Role changed': 'Rôle modifié',
@@ -3185,7 +3154,6 @@ export const messages = {
"The owner can't be changed or removed. Transfer ownership first.":
'Le propriétaire ne peut être ni modifié ni retiré. Transférez d’abord la propriété.',
'Their API keys follow the new role.': 'Ses clés d’API suivent le nouveau rôle.',
'Their role changed meanwhile': 'Son rôle a changé entre-temps',
'There is one owner. Transfer ownership to change who it is.':
'Il n’y a qu’un propriétaire. Transférez la propriété pour changer de propriétaire.',
'They get an email with a link to set a password.':
@@ -3211,9 +3179,127 @@ export const messages = {
'{0} becomes the owner.': '{0} devient propriétaire.',
'{0} is now the owner. You are an Admin.': '{0} est maintenant propriétaire. Vous êtes Admin.',
'{0} members have this role.': '{0} membres ont ce rôle.',
'{0} now has the {1} role.': '{0} a maintenant le rôle {1}.',
'{0}: {1} → {2}': '{0} : {1} → {2}',
"{0}'s role changed from {1} to {2}": 'Le rôle de {0} est passé de {1} à {2}',
'{0} is now {1}, and their API keys follow the new role.':
'{0} a maintenant le rôle {1}, et ses clés API suivent le nouveau rôle.',
"Couldn't save the role": "Impossible d'enregistrer le rôle",
'Your changes are still here. Try again in a moment.':
'Vos modifications sont toujours là. Réessayez dans un instant.',
"Couldn't change the role": 'Impossible de modifier le rôle',
'{0} no longer exists': "{0} n'existe plus",
'It was deleted somewhere else. Choose another role to move the members to.':
'Il a été supprimé ailleurs. Choisissez un autre rôle pour y déplacer les membres.',
'Role still has members': 'Le rôle a encore des membres',
'{0} now has 1 member. Move them to another role first.':
"{0} a maintenant 1 membre. Déplacez-le d'abord vers un autre rôle.",
'{0} now has {1} members. Move them to another role first.':
"{0} a maintenant {1} membres. Déplacez-les d'abord vers un autre rôle.",
"Couldn't move the members": 'Impossible de déplacer les membres',
'Enter a valid email address.': 'Saisissez une adresse e-mail valide.',
"Couldn't send the invite": "Impossible d'envoyer l'invitation",
'Moved {0} members from {1} to {2}': '{0} membres déplacés de {1} vers {2}',
'Moved 1 member from {0} to {1}': '1 membre déplacé de {0} vers {1}',
'Moved {0} members from {1} to another role': '{0} membres déplacés de {1} vers un autre rôle',
'Moved 1 member from {0} to another role': '1 membre déplacé de {0} vers un autre rôle',
'Failed to move {0} members from {1} to {2}':
'Échec du déplacement de {0} membres de {1} vers {2}',
'Failed to move 1 member from {0} to {1}': 'Échec du déplacement de 1 membre de {0} vers {1}',
'Failed to move {0} members from {1} to another role':
'Échec du déplacement de {0} membres de {1} vers un autre rôle',
'Failed to move 1 member from {0} to another role':
'Échec du déplacement de 1 membre de {0} vers un autre rôle',
'Removed {0}': '{0} retiré',
'Failed to remove {0}': 'Échec du retrait de {0}',
'Move 1 member and delete role': 'Déplacer 1 membre et supprimer le rôle',
'Showing {0} of {1}': 'Affichage de {0} sur {1}',
Reload: 'Recharger',
'Role changed elsewhere': 'Rôle modifié ailleurs',
'{0} edited {1}, so nothing was saved. Reload and try again.':
"{0} a modifié {1}, donc rien n'a été enregistré. Rechargez et réessayez.",
'That role no longer exists': "Ce rôle n'existe plus",
'Role not changed': 'Rôle non modifié',
"{0}'s role changed in the meantime, so nothing was saved. Reload and try again.":
"Le rôle de {0} a changé entre-temps, donc rien n'a été enregistré. Rechargez et réessayez.",
'Ownership not transferred': 'Propriété non transférée',
"{0}'s role changed in the meantime, so nothing was transferred. Check it and try again.":
"Le rôle de {0} a changé entre-temps, donc rien n'a été transféré. Vérifiez-le et réessayez.",
'User not removed': 'Utilisateur non retiré',
"{0}'s role changed in the meantime, so nothing was removed. Check it and try again.":
"Le rôle de {0} a changé entre-temps, donc rien n'a été retiré. Vérifiez-le et réessayez.",
'How the saved role differs from your edits':
'Comment le rôle enregistré diffère de vos modifications',
Setting: 'Réglage',
Yours: 'Vous',
'Use the saved role': 'Utiliser le rôle enregistré',
'Keep my edits': 'Garder mes modifications',
'Role reloaded': 'Rôle rechargé',
'Your {0} changes are still here. Review them, then save.':
'Vos {0} modifications sont toujours là. Relisez-les, puis enregistrez.',
'Read: Own': 'Lecture : Les siennes',
"Articles show online articles plus the person's own drafts. Custom content types show only entries the person created. Status counts follow the same rule.":
"Les articles affichent les articles en ligne et les brouillons de la personne. Les types de contenu personnalisés n'affichent que les entrées créées par la personne. Les compteurs de statut suivent la même règle.",
'Role changed in the meantime': 'Rôle modifié entre-temps',
'{0} is now {1}. Your choice is kept. Check it and try again.':
'{0} a maintenant le rôle {1}. Votre choix est conservé. Vérifiez-le et réessayez.',
'{0} is now {1}. What you typed is kept. Check the change, then try again.':
'{0} a maintenant le rôle {1}. Ce que vous avez saisi est conservé. Vérifiez le changement, puis réessayez.',
'Reload member': 'Recharger le membre',
'Create a content type. Needs the permission "Create and edit content types".':
'Crée un type de contenu. Nécessite la permission « Créer et modifier des types de contenu ».',
'Replace the name, icon and fields of a type. The key never changes. Saved field keys and types can\'t change. Needs the permission "Create and edit content types".':
'Remplace le nom, l’icône et les champs d’un type. La clé ne change jamais. Les clés et types des champs enregistrés ne peuvent pas changer. Nécessite la permission « Créer et modifier des types de contenu ».',
'Delete a content type. Only possible when it has no entries and no relation field points at it. Needs the permission "Delete content types".':
'Supprime un type de contenu. Possible seulement s’il n’a aucune entrée et si aucun champ de relation ne pointe vers lui. Nécessite la permission « Supprimer des types de contenu ».',
'List the built-in types (Articles, Authors, Sites, Media, Users) and their fields. Keys are article, author, site, media and user. Needs the permission "View content types".':
'Liste les types intégrés (articles, auteurs, sites, médias, utilisateurs) et leurs champs. Les clés sont article, author, site, media et user. Nécessite la permission « Voir les types de contenu ».',
'Get one built-in type. Keys are article, author, site, media and user. Needs the permission "View content types".':
'Renvoie un type intégré. Les clés sont article, author, site, media et user. Nécessite la permission « Voir les types de contenu ».',
'Get the automatic duplicate purge settings. Needs the permission "View settings".':
'Récupère les paramètres de la purge automatique des doublons. Nécessite la permission « Voir les paramètres ».',
'Turn the automatic purge on or off, or change its interval. Needs the permission "Edit general settings".':
'Active ou désactive la purge automatique, ou modifie son intervalle. Nécessite la permission « Modifier les paramètres généraux ».',
'Preview what a purge would merge. Nothing changes. Needs the permission "Delete files".':
'Prévisualise ce qu’une purge fusionnerait. Rien n’est modifié. Nécessite la permission « Supprimer des fichiers ».',
'Merge every group of identical copies. Send the preview fingerprint to refuse a changed library. failed_groups counts groups that could not be purged; the others were still purged. Needs the permission "Delete files".':
'Fusionne chaque groupe de copies identiques. Envoyez l’empreinte de l’aperçu pour refuser une bibliothèque modifiée. failed_groups compte les groupes qui n’ont pas pu être purgés ; les autres l’ont été. Nécessite la permission « Supprimer des fichiers ».',
'Define your own kind of content, like events or recipes. A user whose role can create and edit content types defines a type made of 1 to 50 ordered fields; the type then has its own entry routes.':
'Définissez votre propre type de contenu, comme des événements ou des recettes. Une personne dont le rôle peut créer et modifier des types de contenu définit un type composé de 1 à 50 champs ordonnés ; le type a alors ses propres routes d’entrées.',
"Read and write the content of a custom type. Each route needs the matching content permission of the key creator's role.":
'Lisez et écrivez le contenu d’un type personnalisé. Chaque route exige l’autorisation de contenu correspondante du rôle du créateur de la clé.',
'Send `Authorization: Bearer rcms_…`. Requests act as the user who created the key, with that user\'s role as it is now. A key never has more rights than its creator. A route that needs a permission answers 403 "missing_permission" to a key whose creator\'s role lacks it.':
'Envoyez `Authorization: Bearer rcms_…`. Les requêtes agissent comme la personne qui a créé la clé, avec son rôle tel qu’il est actuellement. Une clé n’a jamais plus de droits que son créateur. Une route qui exige une permission répond 403 « missing_permission » à une clé dont le rôle du créateur ne la possède pas.',
'`missing_permission` is the literal body, not a sentence. Site SEO defaults need the permission to manage sites. Article SEO fields need only the right to edit the article.':
'`missing_permission` est le corps littéral de la réponse, pas une phrase. Les valeurs SEO par défaut d’un site demandent la permission de gérer les sites. Les champs SEO d’un article demandent seulement le droit de modifier l’article.',
'Needs permission': 'Autorisation requise',
'{0} saved changes to {1} at {2}.': '{0} a enregistré des modifications sur {1} à {2}.',
'Your 1 change is still here. Review it, then save.':
'Votre 1 modification est toujours là. Relisez-la, puis enregistrez.',
'Remove user': 'Retirer l’utilisateur',
"You can't remove yourself. Ask another owner or admin.":
'Vous ne pouvez pas vous retirer vous-même. Demandez à un autre propriétaire ou administrateur.',
'Remove {0}?': 'Retirer {0} ?',
'They lose access straight away, and the API keys they created stop working. Their articles, entries and media stay.':
'Cette personne perd l’accès immédiatement, et les clés API qu’elle a créées cessent de fonctionner. Ses articles, entrées et médias restent.',
"Couldn't remove the user": 'Impossible de retirer l’utilisateur',
'User removed': 'Utilisateur retiré',
'{0} no longer has access.': '{0} n’a plus accès.',
'Online articles and the drafts you created.':
'Les articles en ligne et les brouillons que vous avez créés.',
'Drafts by others are hidden': 'Les brouillons des autres sont masqués',
'Your role reads online articles and the drafts you created. The counts follow the same rule.':
'Votre rôle lit les articles en ligne et les brouillons que vous avez créés. Les compteurs suivent la même règle.',
'You have no drafts': 'Vous n’avez aucun brouillon',
"Drafts you create appear here. Your role can't see drafts by other people.":
'Les brouillons que vous créez apparaissent ici. Votre rôle ne peut pas voir les brouillons des autres personnes.',
'Your role shows only entries you created.':
'Votre rôle n’affiche que les entrées que vous avez créées.',
"Entries by others aren't shown": 'Les entrées des autres ne sont pas affichées',
'Your role reads only entries you created. Ask an owner or admin if you need to see more.':
'Votre rôle ne lit que les entrées que vous avez créées. Demandez à un propriétaire ou administrateur si vous avez besoin d’en voir plus.',
"You haven't created {0} yet": 'Vous n’avez pas encore créé d’entrée dans {0}',
"Your role shows only entries you created, so other people's {0} aren't listed here. Use New entry to add one.":
'Votre rôle n’affiche que les entrées que vous avez créées, donc les entrées des autres personnes dans {0} ne sont pas listées ici. Utilisez Nouvelle entrée pour en ajouter une.',
} as const
export type MessageKey = keyof typeof messages