0.13.22 : tell a join request apart from an invitation
Build release Docker image / Build Docker Images (push) Successful in 8m5s

Le controller forçait `state = "pending_user_approval"` quel que soit le
sens — commentaire à l'appui : « On force le statut en attente peu
importe le type d'invité ». Une candidature déposée par un utilisateur
ressortait donc en invitation, et il recevait un email « vous avez été
invité » pour une chorale qu'il venait lui-même de demander à rejoindre.

- une adhésion créée par un utilisateur pour lui-même est une
  candidature : `pending_admin_approval`, à valider par un administrateur
- rôle imposé à `member` dans ce cas : sans cela, une candidature pouvait
  se déclarer `owner` de la chorale visée
- aucun email d'invitation n'est envoyé pour une candidature
- l'invitation, elle, garde son comportement : `pending_user_approval`,
  token pour un email externe, notification pour un compte existant

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-27 14:02:01 +02:00
parent e168b6c826
commit 62064f053a
2 changed files with 25 additions and 9 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "harmony-back",
"version": "0.13.21",
"version": "0.13.22",
"private": true,
"description": "A Strapi application",
"scripts": {
@@ -8,19 +8,33 @@ export default factories.createCoreController(
const { data } = ctx.request.body;
const inviter = ctx.state.user;
// 1. Déterminer le type d'invitation
// 1. Déterminer le sens de la demande.
// Une adhésion peut naître dans deux sens opposés, que ce controller
// confondait : il forçait `pending_user_approval` et envoyait un
// email d'invitation dans tous les cas — y compris à quelqu'un qui
// venait lui-même de demander à rejoindre la chorale.
const isSelfRequest =
!!data.user && !!inviter?.id && String(data.user) === String(inviter.id);
const isExternalInvite = !!data.invite_email && !data.user;
const isInternalInvite = !!data.user;
const isInternalInvite = !!data.user && !isSelfRequest;
let token = null;
let targetEmail = null;
// 2. Configuration commune
// On force le statut "en attente" peut importe le type d'invité
// 2. Statut selon le sens : c'est à l'autre partie de se prononcer.
if (isSelfRequest) {
ctx.request.body.data.state = "pending_admin_approval";
// Rôle imposé : sans cela, une candidature pourrait se déclarer
// `owner` de la chorale qu'elle demande à rejoindre.
ctx.request.body.data.role = "member";
ctx.request.body.data.invite_token = null;
ctx.request.body.data.invite_email = null;
} else {
ctx.request.body.data.state = "pending_user_approval";
if (!data.role) {
ctx.request.body.data.role = "member";
}
}
// 3. Traitement spécifique selon le cas
if (isExternalInvite) {
@@ -51,8 +65,10 @@ export default factories.createCoreController(
// 4. Exécution de la création native par Strapi
const response = await super.create(ctx);
// 5. Post-traitement : Envoi de l'email
if (response && targetEmail) {
// 5. Post-traitement : Envoi de l'email d'invitation.
// Jamais pour une candidature : `targetEmail` reste nul dans ce cas,
// on n'écrit pas « vous avez été invité » à qui vient de postuler.
if (response && targetEmail && !isSelfRequest) {
try {
const chorals = await strapi
.documents("api::choral.choral")