From c33debf153ff04d5b26b7ce383cb6fe42ffb0347 Mon Sep 17 00:00:00 2001 From: julien vdb Date: Sat, 15 Nov 2025 18:13:24 +0100 Subject: [PATCH] 0.12.4 : improve find user --- package.json | 2 +- .../1.0.0/full_documentation.json | 77 +++++++- .../content-types/user/schema.json | 3 + .../users-permissions/strapi-server.ts | 170 ++++++++++++++++++ types/generated/contentTypes.d.ts | 1 + 5 files changed, 251 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 45355a2..38c8c46 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "harmony-back", - "version": "0.12.3", + "version": "0.12.4", "private": true, "description": "A Strapi application", "scripts": { diff --git a/src/extensions/documentation/documentation/1.0.0/full_documentation.json b/src/extensions/documentation/documentation/1.0.0/full_documentation.json index c409641..0d315e2 100644 --- a/src/extensions/documentation/documentation/1.0.0/full_documentation.json +++ b/src/extensions/documentation/documentation/1.0.0/full_documentation.json @@ -14,7 +14,7 @@ "name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html" }, - "x-generation-date": "2025-11-13T22:01:13.582Z" + "x-generation-date": "2025-11-15T17:13:07.860Z" }, "x-strapi-config": { "plugins": [ @@ -17873,6 +17873,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -21530,6 +21533,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -25469,6 +25475,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -28967,6 +28976,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -32913,6 +32925,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -37110,6 +37125,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -41756,6 +41774,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -45692,6 +45713,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -49530,6 +49554,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -53355,6 +53382,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -57216,6 +57246,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -60969,6 +61002,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -64899,6 +64935,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -68902,6 +68941,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -72394,6 +72436,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -76815,6 +76860,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -80625,6 +80673,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -84756,6 +84807,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -88599,6 +88653,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -92546,6 +92603,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -96394,6 +96454,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -99747,6 +99810,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -104309,6 +104375,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -108200,6 +108269,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" @@ -112051,6 +112123,9 @@ "privacy": { "$ref": "#/components/schemas/ConfigurationPrivacyComponent" }, + "education": { + "type": "string" + }, "createdAt": { "type": "string", "format": "date-time" diff --git a/src/extensions/users-permissions/content-types/user/schema.json b/src/extensions/users-permissions/content-types/user/schema.json index 74fc19c..64974c5 100644 --- a/src/extensions/users-permissions/content-types/user/schema.json +++ b/src/extensions/users-permissions/content-types/user/schema.json @@ -235,6 +235,9 @@ "type": "component", "repeatable": false, "component": "configuration.privacy" + }, + "education": { + "type": "string" } } } diff --git a/src/extensions/users-permissions/strapi-server.ts b/src/extensions/users-permissions/strapi-server.ts index 7efff29..aebdf38 100644 --- a/src/extensions/users-permissions/strapi-server.ts +++ b/src/extensions/users-permissions/strapi-server.ts @@ -99,6 +99,28 @@ module.exports = (plugin) => { populate: true, }); + if (fullUser.contacts && Array.isArray(fullUser.contacts)) { + fullUser.contacts = fullUser.contacts.filter( + (contact) => contact.state === "accepted" + ); + } + + if (fullUser.post_ownerships && Array.isArray(fullUser.post_ownerships)) { + fullUser.post_ownerships = fullUser.post_ownerships.filter( + (ownership) => + ownership.contextType === "user" && ownership.relation === "owner" + ); + } + + if ( + fullUser.group_memberships && + Array.isArray(fullUser.group_memberships) + ) { + fullUser.group_memberships = fullUser.group_memberships.filter( + (membership) => ["member", "admin", "owner"].includes(membership.role) + ); + } + const user = ctx.state.user; const userId = user.id; @@ -156,6 +178,154 @@ module.exports = (plugin) => { return result; }; + const originalFindOne = plugin.controllers.user.findOne; + + plugin.controllers.user.findOne = async (ctx) => { + // 1️⃣ Appel du controller d'origine (permissions, policies) + await originalFindOne(ctx); + + // 2️⃣ Récupère l'utilisateur renvoyé + let user = ctx.body; + + if (!user) { + return ctx.notFound("User not found"); + } + + // 4️⃣ Ajoute un champ calculé + user.profileCompleted = Boolean(user.username && user.surname); + + // 3️⃣ Supprime les champs sensibles + const sensitive = ["password", "resetPasswordToken", "confirmationToken"]; + sensitive.forEach((key) => delete user[key]); //post_ownerships + + // 5️⃣ Refetch avec relations peuplées + try { + const populatedUser = await strapi.entityService.findOne( + "plugin::users-permissions.user", + user.id, + { + populate: { + post_ownerships: { + populate: { + post: { + populate: { + media: true, + }, + }, + }, + }, + contacts: { + populate: { + owner: { + populate: { + avatar: true, + }, + }, + user: { + populate: { + avatar: true, + }, + }, + }, + }, + group_memberships: { + populate: { + group: { + populate: { + banner: true, + }, + }, + }, + }, + activities: true, + }, + } + ); + // Fusionne les données originales (permissions/serialization) avec les relations + user = { ...user, ...populatedUser }; + + if (user.contacts && Array.isArray(user.contacts)) { + user.contacts = user.contacts.filter( + (contact) => contact.state === "accepted" + ); + } + + if (user.post_ownerships && Array.isArray(user.post_ownerships)) { + user.post_ownerships = user.post_ownerships.filter( + (ownership) => + ownership.contextType === "user" && ownership.relation === "owner" + ); + } + + if (user.group_memberships && Array.isArray(user.group_memberships)) { + user.group_memberships = user.group_memberships.filter((membership) => + ["member", "admin", "owner"].includes(membership.role) + ); + } + + const eventRelationships = await strapi.db + .query("api::event-relationship.event-relationship") + .findMany({ + where: { author: user.id, relation: "owner", contextType: "user" }, + populate: { + event: true, + }, + }); + user.event_relationships = eventRelationships || []; + const [ + contactsCount, + groupsCount, + postsCount, + eventsCount, + followersCount, + followingCount, + ] = await Promise.all([ + strapi.db.query("api::contact.contact").count({ + where: { + $or: [{ owner: user.id }, { user: user.id }], + }, + }), + strapi.db.query("api::group-membership.group-membership").count({ + where: { + user: user.id, + role: { $in: ["owner", "member", "admin"] }, + }, + }), + strapi.db + .query("api::post-ownership.post-ownership") + .count({ where: { author: user.id } }), + strapi.db + .query("api::event-relationship.event-relationship") + .count({ where: { author: user.id } }), + strapi.db.query("api::contact.contact").count({ + where: { + user: user.id, + state: "follow", + }, + }), + strapi.db.query("api::contact.contact").count({ + where: { + owner: user.id, + state: "follow", + }, + }), + ]); + user.stats = { + contacts: contactsCount, + groups: groupsCount, + posts: postsCount, + events: eventsCount, + followers: followersCount, + following: followingCount, + }; + } catch (err) { + console.error("Erreur populate relations user:", err); + // fallback : retourne juste l'utilisateur original + } + ctx.body = user; + return ctx; + }; + const uploadImage = async (ctx, label: string, username: string) => { const key = `${label}Image`; if (ctx.request.files[key]) { diff --git a/types/generated/contentTypes.d.ts b/types/generated/contentTypes.d.ts index f779f08..e483817 100644 --- a/types/generated/contentTypes.d.ts +++ b/types/generated/contentTypes.d.ts @@ -1863,6 +1863,7 @@ export interface PluginUsersPermissionsUser createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; dob: Schema.Attribute.Date; + education: Schema.Attribute.String; email: Schema.Attribute.Email & Schema.Attribute.Required & Schema.Attribute.SetMinMaxLength<{