Change schema and feed

This commit is contained in:
2025-09-30 23:32:18 +02:00
parent e7f91f1a7f
commit 2964a58827
7 changed files with 13421 additions and 13718 deletions

View File

@@ -12,12 +12,6 @@
}, },
"pluginOptions": {}, "pluginOptions": {},
"attributes": { "attributes": {
"post": {
"type": "relation",
"relation": "oneToOne",
"target": "api::post.post",
"inversedBy": "post_ownership"
},
"author": { "author": {
"type": "relation", "type": "relation",
"relation": "manyToOne", "relation": "manyToOne",
@@ -45,6 +39,12 @@
}, },
"metas": { "metas": {
"type": "json" "type": "json"
},
"post": {
"type": "relation",
"relation": "manyToOne",
"target": "api::post.post",
"inversedBy": "post_ownerships"
} }
} }
} }

View File

@@ -26,12 +26,6 @@
"audios" "audios"
] ]
}, },
"author": {
"type": "relation",
"relation": "manyToOne",
"target": "plugin::users-permissions.user",
"inversedBy": "posts"
},
"likes": { "likes": {
"type": "relation", "type": "relation",
"relation": "oneToMany", "relation": "oneToMany",
@@ -65,9 +59,9 @@
"source": { "source": {
"type": "string" "type": "string"
}, },
"post_ownership": { "post_ownerships": {
"type": "relation", "type": "relation",
"relation": "oneToOne", "relation": "oneToMany",
"target": "api::post-ownership.post-ownership", "target": "api::post-ownership.post-ownership",
"mappedBy": "post" "mappedBy": "post"
} }

View File

@@ -48,6 +48,14 @@ export default factories.createCoreController(
return result; return result;
}, },
/**
* Retrieves the feed for the authenticated user, including posts from friends, followed contacts,
* user's groups, friends' groups, and system posts. The feed is enriched with additional properties
* such as friend, contactFollow, member, and group.
*
* @param {Object} ctx - The Koa context object containing the request and response.
* @returns {Promise<void>} - Sends the enriched feed as the response.
*/
async feed(ctx) { async feed(ctx) {
const userId = ctx.state.user?.id; const userId = ctx.state.user?.id;
const { _limit = 20, _start = 0 } = ctx.query; const { _limit = 20, _start = 0 } = ctx.query;
@@ -144,6 +152,11 @@ export default factories.createCoreController(
.query("api::post-ownership.post-ownership") .query("api::post-ownership.post-ownership")
.findMany({ .findMany({
where: { where: {
$or: [
// Posts réguliers (amis, follows, groupes, système) - exclure les cachés
{
$and: [
{
$or: [ $or: [
{ author: { id: friendIds } }, // Posts de mes amis { author: { id: friendIds } }, // Posts de mes amis
{ author: { id: followIds } }, // Posts des contacts que je suis { author: { id: followIds } }, // Posts des contacts que je suis
@@ -151,7 +164,23 @@ export default factories.createCoreController(
{ contextType: "group", contextId: friendsGroupIds }, // Posts des groupes de mes amis { contextType: "group", contextId: friendsGroupIds }, // Posts des groupes de mes amis
{ contextType: "system" }, // Posts système { contextType: "system" }, // Posts système
], ],
relation: { $ne: "hidden" }, // exclure les posts masqués },
{ relation: { $ne: "hidden" } }, // exclure les posts masqués pour les posts réguliers
],
},
// Posts sauvés par l'utilisateur
{
contextType: "user",
contextId: parseInt(userId),
relation: "saved",
},
// Posts cachés par l'utilisateur
{
contextType: "user",
contextId: parseInt(userId),
relation: "hidden",
},
],
}, },
...queryParams, ...queryParams,
}); });
@@ -225,41 +254,239 @@ export default factories.createCoreController(
return ctx.notFound("Post not found"); return ctx.notFound("Post not found");
} }
// Get current user with saved_posts // Check if post is already saved by this user
const currentUser: any = await strapi.entityService.findOne( const existingSavedPost = await strapi.db
"plugin::users-permissions.user", .query("api::post-ownership.post-ownership")
user.id, .findOne({
{ populate: ["saved_posts"] } where: {
); post: postId,
author: user.id,
// Initialize saved_posts array if it doesn't exist contextType: "user",
const currentSavedPosts = currentUser.saved_posts || []; contextId: user.id,
relation: "saved",
// Check if post is already saved to avoid duplicates
if (currentSavedPosts.some((savedPost: any) => savedPost.id === postId)) {
console.log("⚠️ Post already saved");
return ctx.badRequest("Post already saved");
}
// Add the post to saved_posts
const updatedSavedPosts = [...currentSavedPosts, postId];
console.log("🔄 Updating user with new saved posts:", updatedSavedPosts);
// Update the user
const updatedUser = await strapi.entityService.update(
"plugin::users-permissions.user",
user.id,
{
data: {
saved_posts: updatedSavedPosts as any,
}, },
});
if (existingSavedPost) {
console.log("⚠️ Post already saved");
return ctx.badRequest("Post is already saved");
} }
);
// Create postOwnership entry to mark post as saved
const savedPostOwnership = await strapi.db
.query("api::post-ownership.post-ownership")
.create({
data: {
post: postId,
author: user.id,
contextType: "user",
contextId: user.id,
relation: "saved",
},
});
console.log("✅ Post marked as saved:", savedPostOwnership);
// Get count of saved posts for this user
const savedPostsCount = await strapi.db
.query("api::post-ownership.post-ownership")
.count({
where: {
author: user.id,
contextType: "user",
contextId: user.id,
relation: "saved",
},
});
return ctx.send({ return ctx.send({
message: "Post saved successfully", message: "Post saved successfully",
savedPostsCount: updatedSavedPosts.length, savedPostsCount: savedPostsCount,
});
},
async removeSavedPost(ctx) {
console.log("🎯 removeSavedPost called with params:", ctx.params);
console.log("🎯 Request method:", ctx.request.method);
console.log("🎯 Request URL:", ctx.request.url);
const user = ctx.state.user;
if (!user) {
console.log("❌ User not authenticated");
return ctx.unauthorized("You must be logged in to remove saved posts");
}
console.log("✅ User authenticated:", user.id);
const postId = parseInt(ctx.params.id);
if (isNaN(postId)) {
return ctx.badRequest("Invalid post ID");
}
// Verify the post exists
const post = await strapi.entityService.findOne("api::post.post", postId);
if (!post) {
return ctx.notFound("Post not found");
}
// Find the saved post ownership entry
const savedPostOwnership = await strapi.db
.query("api::post-ownership.post-ownership")
.findOne({
where: {
post: postId,
author: user.id,
contextType: "user",
contextId: user.id,
relation: "saved",
},
});
if (!savedPostOwnership) {
console.log("⚠️ Post is not saved");
return ctx.badRequest("Post is not in your saved posts");
}
// Delete the saved post ownership entry
await strapi.db.query("api::post-ownership.post-ownership").delete({
where: { id: savedPostOwnership.id },
});
console.log("✅ Post removed from saved posts successfully");
// Get updated count of saved posts for this user
const savedPostsCount = await strapi.db
.query("api::post-ownership.post-ownership")
.count({
where: {
author: user.id,
contextType: "user",
contextId: user.id,
relation: "saved",
},
});
return ctx.send({
message: "Post removed from saved posts successfully",
savedPostsCount: savedPostsCount,
});
},
async hidePost(ctx) {
console.log("🎯 hidePost called with params:", ctx.params);
console.log("🎯 Request method:", ctx.request.method);
console.log("🎯 Request URL:", ctx.request.url);
const user = ctx.state.user;
if (!user) {
console.log("❌ User not authenticated");
return ctx.unauthorized("You must be logged in to hide posts");
}
console.log("✅ User authenticated:", user.id);
const postId = parseInt(ctx.params.id);
if (isNaN(postId)) {
return ctx.badRequest("Invalid post ID");
}
// Verify the post exists
const post = await strapi.entityService.findOne("api::post.post", postId);
if (!post) {
return ctx.notFound("Post not found");
}
// Check if post is already hidden by this user
const existingHiddenPost = await strapi.db
.query("api::post-ownership.post-ownership")
.findOne({
where: {
post: postId,
author: user.id,
contextType: "user",
contextId: user.id,
relation: "hidden",
},
});
if (existingHiddenPost) {
console.log("⚠️ Post already hidden");
return ctx.badRequest("Post is already hidden");
}
// Create postOwnership entry to mark post as hidden
const hiddenPostOwnership = await strapi.db
.query("api::post-ownership.post-ownership")
.create({
data: {
post: postId,
author: user.id,
contextType: "user",
contextId: user.id,
relation: "hidden",
},
});
console.log("✅ Post marked as hidden:", hiddenPostOwnership);
return ctx.send({
message: "Post hidden successfully",
hiddenPostId: postId,
});
},
async removeHiddenPost(ctx) {
console.log("🎯 removeHiddenPost called with params:", ctx.params);
console.log("🎯 Request method:", ctx.request.method);
console.log("🎯 Request URL:", ctx.request.url);
const user = ctx.state.user;
if (!user) {
console.log("❌ User not authenticated");
return ctx.unauthorized("You must be logged in to unhide posts");
}
console.log("✅ User authenticated:", user.id);
const postId = parseInt(ctx.params.id);
if (isNaN(postId)) {
return ctx.badRequest("Invalid post ID");
}
// Verify the post exists
const post = await strapi.entityService.findOne("api::post.post", postId);
if (!post) {
return ctx.notFound("Post not found");
}
// Find the hidden post ownership entry
const hiddenPostOwnership = await strapi.db
.query("api::post-ownership.post-ownership")
.findOne({
where: {
post: postId,
author: user.id,
contextType: "user",
contextId: user.id,
relation: "hidden",
},
});
if (!hiddenPostOwnership) {
console.log("⚠️ Post is not hidden");
return ctx.badRequest("Post is not hidden");
}
// Delete the hidden post ownership entry
await strapi.db.query("api::post-ownership.post-ownership").delete({
where: { id: hiddenPostOwnership.id },
});
console.log("✅ Post unhidden successfully");
return ctx.send({
message: "Post unhidden successfully",
unhiddenPostId: postId,
}); });
}, },
}) })

View File

@@ -9,6 +9,21 @@ export default {
path: "/posts/:id/save", path: "/posts/:id/save",
handler: "post.savePost", handler: "post.savePost",
}, },
{
method: "DELETE",
path: "/posts/:id/save",
handler: "post.removeSavedPost",
},
{
method: "POST",
path: "/posts/:id/hide",
handler: "post.hidePost",
},
{
method: "DELETE",
path: "/posts/:id/hide",
handler: "post.removeHiddenPost",
},
{ {
method: "GET", method: "GET",
path: "/posts/feed", path: "/posts/feed",

View File

@@ -182,12 +182,6 @@
"target": "api::announcement.announcement", "target": "api::announcement.announcement",
"mappedBy": "author" "mappedBy": "author"
}, },
"posts": {
"type": "relation",
"relation": "oneToMany",
"target": "api::post.post",
"mappedBy": "author"
},
"friends": { "friends": {
"type": "relation", "type": "relation",
"relation": "oneToMany", "relation": "oneToMany",

View File

@@ -1209,7 +1209,7 @@ export interface ApiPostOwnershipPostOwnership
> & > &
Schema.Attribute.Private; Schema.Attribute.Private;
metas: Schema.Attribute.JSON; metas: Schema.Attribute.JSON;
post: Schema.Attribute.Relation<'oneToOne', 'api::post.post'>; post: Schema.Attribute.Relation<'manyToOne', 'api::post.post'>;
publishedAt: Schema.Attribute.DateTime; publishedAt: Schema.Attribute.DateTime;
relation: Schema.Attribute.Enumeration<['owner', 'saved', 'hidden']>; relation: Schema.Attribute.Enumeration<['owner', 'saved', 'hidden']>;
updatedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime;
@@ -1230,10 +1230,6 @@ export interface ApiPostPost extends Struct.CollectionTypeSchema {
draftAndPublish: false; draftAndPublish: false;
}; };
attributes: { attributes: {
author: Schema.Attribute.Relation<
'manyToOne',
'plugin::users-permissions.user'
>;
category: Schema.Attribute.Enumeration<['photo', 'video', 'event']>; category: Schema.Attribute.Enumeration<['photo', 'video', 'event']>;
comments: Schema.Attribute.Relation<'oneToMany', 'api::comment.comment'>; comments: Schema.Attribute.Relation<'oneToMany', 'api::comment.comment'>;
content: Schema.Attribute.Text; content: Schema.Attribute.Text;
@@ -1252,8 +1248,8 @@ export interface ApiPostPost extends Struct.CollectionTypeSchema {
'images' | 'files' | 'videos' | 'audios', 'images' | 'files' | 'videos' | 'audios',
true true
>; >;
post_ownership: Schema.Attribute.Relation< post_ownerships: Schema.Attribute.Relation<
'oneToOne', 'oneToMany',
'api::post-ownership.post-ownership' 'api::post-ownership.post-ownership'
>; >;
publishedAt: Schema.Attribute.DateTime; publishedAt: Schema.Attribute.DateTime;
@@ -1831,7 +1827,6 @@ export interface PluginUsersPermissionsUser
'oneToMany', 'oneToMany',
'api::post-ownership.post-ownership' 'api::post-ownership.post-ownership'
>; >;
posts: Schema.Attribute.Relation<'oneToMany', 'api::post.post'>;
provider: Schema.Attribute.String; provider: Schema.Attribute.String;
publishedAt: Schema.Attribute.DateTime; publishedAt: Schema.Attribute.DateTime;
related_contacts: Schema.Attribute.Relation< related_contacts: Schema.Attribute.Relation<