Change schema and feed
This commit is contained in:
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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",
|
||||||
|
|||||||
11
types/generated/contentTypes.d.ts
vendored
11
types/generated/contentTypes.d.ts
vendored
@@ -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<
|
||||||
|
|||||||
Reference in New Issue
Block a user