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": {},
"attributes": {
"post": {
"type": "relation",
"relation": "oneToOne",
"target": "api::post.post",
"inversedBy": "post_ownership"
},
"author": {
"type": "relation",
"relation": "manyToOne",
@@ -45,6 +39,12 @@
},
"metas": {
"type": "json"
},
"post": {
"type": "relation",
"relation": "manyToOne",
"target": "api::post.post",
"inversedBy": "post_ownerships"
}
}
}

View File

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

View File

@@ -48,6 +48,14 @@ export default factories.createCoreController(
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) {
const userId = ctx.state.user?.id;
const { _limit = 20, _start = 0 } = ctx.query;
@@ -144,6 +152,11 @@ export default factories.createCoreController(
.query("api::post-ownership.post-ownership")
.findMany({
where: {
$or: [
// Posts réguliers (amis, follows, groupes, système) - exclure les cachés
{
$and: [
{
$or: [
{ author: { id: friendIds } }, // Posts de mes amis
{ 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: "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,
});
@@ -225,41 +254,239 @@ export default factories.createCoreController(
return ctx.notFound("Post not found");
}
// Get current user with saved_posts
const currentUser: any = await strapi.entityService.findOne(
"plugin::users-permissions.user",
user.id,
{ populate: ["saved_posts"] }
);
// Initialize saved_posts array if it doesn't exist
const currentSavedPosts = currentUser.saved_posts || [];
// 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,
// Check if post is already saved by this user
const existingSavedPost = await strapi.db
.query("api::post-ownership.post-ownership")
.findOne({
where: {
post: postId,
author: user.id,
contextType: "user",
contextId: user.id,
relation: "saved",
},
});
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({
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",
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",
path: "/posts/feed",

View File

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

View File

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