Compare commits
10 Commits
1d6e8f3866
...
95ce447496
| Author | SHA1 | Date | |
|---|---|---|---|
| 95ce447496 | |||
| fa993f75b4 | |||
| c33debf153 | |||
| b2e1ab0361 | |||
| 1e642d194e | |||
| b8a2bc0aef | |||
| d64c647865 | |||
| 2bc35b639b | |||
| 14e013bac1 | |||
| 539c9cd104 |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "harmony-back",
|
||||
"version": "0.11.18",
|
||||
"version": "0.12.5",
|
||||
"private": true,
|
||||
"description": "A Strapi application",
|
||||
"scripts": {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"kind": "collectionType",
|
||||
"collectionName": "chat_conversation_members",
|
||||
"info": {
|
||||
"singularName": "chat-conversation-member",
|
||||
"pluralName": "chat-conversation-members",
|
||||
"displayName": "ChatConversationMember"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false
|
||||
},
|
||||
"pluginOptions": {},
|
||||
"attributes": {
|
||||
"user": {
|
||||
"type": "relation",
|
||||
"relation": "oneToOne",
|
||||
"target": "plugin::users-permissions.user"
|
||||
},
|
||||
"role": {
|
||||
"type": "enumeration",
|
||||
"enum": [
|
||||
"member",
|
||||
"admin",
|
||||
"owner"
|
||||
]
|
||||
},
|
||||
"joinedAt": {
|
||||
"type": "datetime"
|
||||
},
|
||||
"lastReadAt": {
|
||||
"type": "datetime"
|
||||
},
|
||||
"conversation": {
|
||||
"type": "relation",
|
||||
"relation": "oneToOne",
|
||||
"target": "api::chat-conversation.chat-conversation"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* chat-conversation-member controller
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi'
|
||||
|
||||
export default factories.createCoreController('api::chat-conversation-member.chat-conversation-member');
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* chat-conversation-member router
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreRouter('api::chat-conversation-member.chat-conversation-member');
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* chat-conversation-member service
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreService('api::chat-conversation-member.chat-conversation-member');
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"kind": "collectionType",
|
||||
"collectionName": "chat_conversations",
|
||||
"info": {
|
||||
"singularName": "chat-conversation",
|
||||
"pluralName": "chat-conversations",
|
||||
"displayName": "ChatConversation",
|
||||
"description": ""
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false
|
||||
},
|
||||
"pluginOptions": {},
|
||||
"attributes": {
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"isGroup": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"creator": {
|
||||
"type": "relation",
|
||||
"relation": "oneToOne",
|
||||
"target": "plugin::users-permissions.user"
|
||||
},
|
||||
"messages": {
|
||||
"type": "relation",
|
||||
"relation": "oneToMany",
|
||||
"target": "api::chat-message.chat-message"
|
||||
},
|
||||
"users": {
|
||||
"type": "relation",
|
||||
"relation": "oneToMany",
|
||||
"target": "plugin::users-permissions.user"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* chat-conversation controller
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi'
|
||||
|
||||
export default factories.createCoreController('api::chat-conversation.chat-conversation');
|
||||
7
src/api/chat-conversation/routes/chat-conversation.ts
Normal file
7
src/api/chat-conversation/routes/chat-conversation.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* chat-conversation router
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreRouter('api::chat-conversation.chat-conversation');
|
||||
7
src/api/chat-conversation/services/chat-conversation.ts
Normal file
7
src/api/chat-conversation/services/chat-conversation.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* chat-conversation service
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreService('api::chat-conversation.chat-conversation');
|
||||
31
src/api/chat-message/content-types/chat-message/schema.json
Normal file
31
src/api/chat-message/content-types/chat-message/schema.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"kind": "collectionType",
|
||||
"collectionName": "chat_messages",
|
||||
"info": {
|
||||
"singularName": "chat-message",
|
||||
"pluralName": "chat-messages",
|
||||
"displayName": "ChatMessage"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false
|
||||
},
|
||||
"pluginOptions": {},
|
||||
"attributes": {
|
||||
"sender": {
|
||||
"type": "relation",
|
||||
"relation": "oneToOne",
|
||||
"target": "plugin::users-permissions.user"
|
||||
},
|
||||
"content": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"isEdited": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"deletedAt": {
|
||||
"type": "datetime"
|
||||
}
|
||||
}
|
||||
}
|
||||
7
src/api/chat-message/controllers/chat-message.ts
Normal file
7
src/api/chat-message/controllers/chat-message.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* chat-message controller
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi'
|
||||
|
||||
export default factories.createCoreController('api::chat-message.chat-message');
|
||||
7
src/api/chat-message/routes/chat-message.ts
Normal file
7
src/api/chat-message/routes/chat-message.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* chat-message router
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreRouter('api::chat-message.chat-message');
|
||||
7
src/api/chat-message/services/chat-message.ts
Normal file
7
src/api/chat-message/services/chat-message.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* chat-message service
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreService('api::chat-message.chat-message');
|
||||
@@ -23,8 +23,10 @@ export default ({ strapi }: { strapi: Core.Strapi }) =>
|
||||
}
|
||||
|
||||
try {
|
||||
const groupId = ctx.request.body.data.group;
|
||||
// Format tags from array of strings to array of component objects
|
||||
const data = ctx.request.body.data;
|
||||
delete data.group;
|
||||
if (data.tags && Array.isArray(data.tags)) {
|
||||
data.tags = data.tags
|
||||
.filter((tag: any) => {
|
||||
@@ -51,14 +53,17 @@ export default ({ strapi }: { strapi: Core.Strapi }) =>
|
||||
}
|
||||
|
||||
// 2. Create the owner relationship
|
||||
const contextType = groupId && groupId !== 0 ? "group" : "user";
|
||||
const contextId = groupId && groupId !== 0 ? groupId : userId;
|
||||
|
||||
const ownerRelationship = await strapi.db
|
||||
.query("api::event-relationship.event-relationship")
|
||||
.create({
|
||||
data: {
|
||||
author: userId,
|
||||
event: event.id,
|
||||
contextType: "user",
|
||||
contextId: userId,
|
||||
contextType,
|
||||
contextId,
|
||||
relation: "owner",
|
||||
metas: {
|
||||
createdAt: new Date().toISOString(),
|
||||
@@ -70,6 +75,16 @@ export default ({ strapi }: { strapi: Core.Strapi }) =>
|
||||
`Event ${event.id} created by user ${userId} with owner relationship ${ownerRelationship.id}`
|
||||
);
|
||||
|
||||
if (contextType === "group") {
|
||||
await strapi
|
||||
.service("api::group.group")
|
||||
.addActivity(
|
||||
contextId,
|
||||
ctx.state.user?.username || `User ${userId}`,
|
||||
`Evènement créé : ${event.title}`
|
||||
);
|
||||
}
|
||||
|
||||
ctx.send({ data: event }, 201);
|
||||
} catch (error) {
|
||||
strapi.log.error("Error in create event controller:", error);
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { Context } from "koa";
|
||||
export default ({ strapi }: { strapi: Core.Strapi }) =>
|
||||
async function feed(ctx: Context) {
|
||||
const userId = ctx.state.user?.id;
|
||||
|
||||
const { contextId, contextType } = ctx.query;
|
||||
if (!userId) return ctx.badRequest("userId is required");
|
||||
|
||||
// Récupérer et valider la query avec les fonctions de Strapi
|
||||
@@ -26,7 +26,12 @@ export default ({ strapi }: { strapi: Core.Strapi }) =>
|
||||
{ auth: ctx.state.auth }
|
||||
);
|
||||
|
||||
const { _limit = 20, _start = 0 } = sanitizedQueryParams;
|
||||
const {
|
||||
_limit = 20,
|
||||
_start = 0,
|
||||
contextType,
|
||||
contextId,
|
||||
} = sanitizedQueryParams;
|
||||
limit = Math.max(1, Math.min(parseInt(String(_limit)) || 20, 100)); // Entre 1 et 100
|
||||
start = Math.max(0, parseInt(String(_start)) || 0); // Minimum 0
|
||||
} catch (error) {
|
||||
@@ -100,50 +105,44 @@ export default ({ strapi }: { strapi: Core.Strapi }) =>
|
||||
.map((membership) => membership.group.id)
|
||||
.filter((groupId) => !groupIds.includes(groupId)); // Exclure mes propres groupes
|
||||
|
||||
// Construire la condition where en fonction des paramètres contextId et contextType
|
||||
const whereCondition =
|
||||
contextId && contextType
|
||||
? {
|
||||
relation: "owner",
|
||||
contextType,
|
||||
contextId: parseInt(String(contextId)),
|
||||
}
|
||||
: {
|
||||
relation: "owner",
|
||||
$or: [
|
||||
// EventRelationships de l'utilisateur courant
|
||||
{ author: { id: parseInt(userId) } },
|
||||
// EventRelationships des amis
|
||||
{ author: { id: friendIds } },
|
||||
// EventRelationships des contacts suivis
|
||||
{ author: { id: followIds } },
|
||||
// EventRelationships des groupes de l'utilisateur
|
||||
{ contextType: "group", contextId: groupIds },
|
||||
// EventRelationships des groupes des amis
|
||||
{ contextType: "group", contextId: friendsGroupIds },
|
||||
// EventRelationships système
|
||||
{ contextType: "system" },
|
||||
],
|
||||
};
|
||||
|
||||
// 4️⃣ Récupérer le count total pour la pagination
|
||||
const totalCount = await strapi.db
|
||||
.query("api::event-relationship.event-relationship")
|
||||
.count({
|
||||
where: {
|
||||
relation: "owner",
|
||||
$or: [
|
||||
// EventRelationships de l'utilisateur courant
|
||||
{ author: { id: parseInt(userId) } },
|
||||
// EventRelationships des amis
|
||||
{ author: { id: friendIds } },
|
||||
// EventRelationships des contacts suivis
|
||||
{ author: { id: followIds } },
|
||||
// EventRelationships des groupes de l'utilisateur
|
||||
{ contextType: "group", contextId: groupIds },
|
||||
// EventRelationships des groupes des amis
|
||||
{ contextType: "group", contextId: friendsGroupIds },
|
||||
// EventRelationships système
|
||||
{ contextType: "system" },
|
||||
],
|
||||
},
|
||||
where: whereCondition,
|
||||
});
|
||||
|
||||
// 4️⃣ Récupérer le feed avec pagination
|
||||
const feed = await strapi.db
|
||||
.query("api::event-relationship.event-relationship")
|
||||
.findMany({
|
||||
where: {
|
||||
relation: "owner",
|
||||
$or: [
|
||||
// EventRelationships de l'utilisateur courant
|
||||
{ author: { id: parseInt(userId) } },
|
||||
// EventRelationships des amis
|
||||
{ author: { id: friendIds } },
|
||||
// EventRelationships des contacts suivis
|
||||
{ author: { id: followIds } },
|
||||
// EventRelationships des groupes de l'utilisateur
|
||||
{ contextType: "group", contextId: groupIds },
|
||||
// EventRelationships des groupes des amis
|
||||
{ contextType: "group", contextId: friendsGroupIds },
|
||||
// EventRelationships système
|
||||
{ contextType: "system" },
|
||||
],
|
||||
},
|
||||
where: whereCondition,
|
||||
...queryParams,
|
||||
});
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
"admin",
|
||||
"owner",
|
||||
"follow",
|
||||
"pending"
|
||||
"pending",
|
||||
"invited",
|
||||
"rejected"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,25 @@ export default factories.createCoreController(
|
||||
);
|
||||
membershipMeta.success = true;
|
||||
membershipMeta.membershipId = membership?.id as number;
|
||||
|
||||
try {
|
||||
await strapi.service("api::notification.notification").createNotification({
|
||||
title: "Groupe créé",
|
||||
message: `Vous avez créé un nouveau groupe`,
|
||||
type: "success",
|
||||
target_user: userId,
|
||||
source: "group-create",
|
||||
payload: {
|
||||
groupId,
|
||||
membershipId: membership?.id,
|
||||
},
|
||||
});
|
||||
} catch (notificationErr: any) {
|
||||
strapi.log.warn(
|
||||
"[group.create] Erreur création notification:",
|
||||
notificationErr
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (err: any) {
|
||||
strapi.log.error(
|
||||
@@ -97,5 +116,98 @@ export default factories.createCoreController(
|
||||
|
||||
return response;
|
||||
},
|
||||
async invite(ctx) {
|
||||
const body = ctx.request.body as any;
|
||||
const data =
|
||||
typeof body?.data === "string"
|
||||
? JSON.parse(body.data)
|
||||
: body?.data || {};
|
||||
|
||||
const groupId = ctx.params.id;
|
||||
const userIds = data?.usersIds || [];
|
||||
|
||||
if (!groupId) {
|
||||
return ctx.badRequest("Missing groupId");
|
||||
}
|
||||
|
||||
if (!Array.isArray(userIds) || userIds.length === 0) {
|
||||
return ctx.badRequest("userIds must be a non-empty array");
|
||||
}
|
||||
|
||||
const results = {
|
||||
success: [],
|
||||
errors: [],
|
||||
};
|
||||
|
||||
for (const userId of userIds) {
|
||||
try {
|
||||
const existingMembership = await strapi.entityService.findMany(
|
||||
"api::group-membership.group-membership",
|
||||
{
|
||||
filters: {
|
||||
user: userId,
|
||||
group: groupId,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (existingMembership && existingMembership.length > 0) {
|
||||
results.errors.push({
|
||||
userId,
|
||||
error: "User is already a member of this group",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const membership = await strapi.entityService.create(
|
||||
"api::group-membership.group-membership",
|
||||
{
|
||||
data: {
|
||||
user: userId,
|
||||
group: groupId,
|
||||
role: "invited",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
try {
|
||||
await strapi.service("api::notification.notification").createNotification({
|
||||
title: "Invitation de groupe",
|
||||
message: `Vous avez été invité à rejoindre un groupe`,
|
||||
type: "info",
|
||||
target_user: userId,
|
||||
source: "group-invite",
|
||||
payload: {
|
||||
groupId,
|
||||
membershipId: membership?.id,
|
||||
},
|
||||
});
|
||||
} catch (notificationErr: any) {
|
||||
strapi.log.warn(
|
||||
"[group.invite] Erreur création notification:",
|
||||
notificationErr
|
||||
);
|
||||
}
|
||||
|
||||
results.success.push({
|
||||
userId,
|
||||
membershipId: membership?.id,
|
||||
});
|
||||
} catch (err: any) {
|
||||
strapi.log.error(
|
||||
"[group.invite] Erreur création GroupMembership:",
|
||||
err
|
||||
);
|
||||
results.errors.push({
|
||||
userId,
|
||||
error: err?.message || "Unknown error",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ctx.body = {
|
||||
data: results,
|
||||
};
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
13
src/api/group/routes/custom.ts
Normal file
13
src/api/group/routes/custom.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Custom post routes
|
||||
*/
|
||||
|
||||
export default {
|
||||
routes: [
|
||||
{
|
||||
method: "POST",
|
||||
path: "/group/:id/invite",
|
||||
handler: "group.invite",
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -4,4 +4,25 @@
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreService('api::group.group');
|
||||
export default factories.createCoreService('api::group.group', ({ strapi }) => ({
|
||||
async addActivity(groupId: number, userName: string, message: string) {
|
||||
const group = await strapi.entityService.findOne('api::group.group', groupId, {
|
||||
populate: ['activities'],
|
||||
}) as any;
|
||||
|
||||
if (!group) {
|
||||
throw new Error(`Group with id ${groupId} not found`);
|
||||
}
|
||||
|
||||
const activities = group.activities || [];
|
||||
activities.push({
|
||||
activityUser: userName,
|
||||
activityMessage: message,
|
||||
activityDate: new Date(),
|
||||
});
|
||||
|
||||
return await strapi.entityService.update('api::group.group', groupId, {
|
||||
data: { activities },
|
||||
});
|
||||
},
|
||||
}));
|
||||
|
||||
22
src/components/configuration/parameter.json
Normal file
22
src/components/configuration/parameter.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"collectionName": "components_configuration_parameters",
|
||||
"info": {
|
||||
"displayName": "parameter",
|
||||
"icon": "cog"
|
||||
},
|
||||
"options": {},
|
||||
"attributes": {
|
||||
"emailNotification": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"pushNotification": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"sendNewsgroup": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/components/configuration/privacy.json
Normal file
35
src/components/configuration/privacy.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"collectionName": "components_configuration_privacies",
|
||||
"info": {
|
||||
"displayName": "privacy",
|
||||
"icon": "key",
|
||||
"description": ""
|
||||
},
|
||||
"options": {},
|
||||
"attributes": {
|
||||
"profileVisibility": {
|
||||
"type": "enumeration",
|
||||
"enum": [
|
||||
"public",
|
||||
"contacts",
|
||||
"private"
|
||||
]
|
||||
},
|
||||
"allowMessage": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"allowInvite": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"allowTag": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"showOnline": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,28 @@
|
||||
},
|
||||
"activityDate": {
|
||||
"type": "datetime"
|
||||
},
|
||||
"activityAvatar": {
|
||||
"type": "media",
|
||||
"multiple": false,
|
||||
"required": false,
|
||||
"allowedTypes": [
|
||||
"images",
|
||||
"files",
|
||||
"videos",
|
||||
"audios"
|
||||
]
|
||||
},
|
||||
"activityType": {
|
||||
"type": "enumeration",
|
||||
"enum": [
|
||||
"user",
|
||||
"group",
|
||||
"choral",
|
||||
"message",
|
||||
"post",
|
||||
"contact"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
17
src/components/user/language.json
Normal file
17
src/components/user/language.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"collectionName": "components_user_languages",
|
||||
"info": {
|
||||
"displayName": "language",
|
||||
"icon": "feather",
|
||||
"description": ""
|
||||
},
|
||||
"options": {},
|
||||
"attributes": {
|
||||
"language": {
|
||||
"type": "string"
|
||||
},
|
||||
"level": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -73,22 +73,6 @@
|
||||
"images"
|
||||
]
|
||||
},
|
||||
"nbFollowers": {
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
},
|
||||
"nbFollowing": {
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
},
|
||||
"nbPosts": {
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
},
|
||||
"nbSaved": {
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
},
|
||||
"choralOwner": {
|
||||
"type": "relation",
|
||||
"relation": "oneToOne",
|
||||
@@ -224,6 +208,36 @@
|
||||
"relation": "oneToMany",
|
||||
"target": "api::post-ownership.post-ownership",
|
||||
"mappedBy": "author"
|
||||
},
|
||||
"activities": {
|
||||
"type": "component",
|
||||
"repeatable": true,
|
||||
"component": "group.activity"
|
||||
},
|
||||
"bio": {
|
||||
"type": "text"
|
||||
},
|
||||
"experience": {
|
||||
"type": "integer"
|
||||
},
|
||||
"tags": {
|
||||
"type": "json"
|
||||
},
|
||||
"languages": {
|
||||
"type": "json"
|
||||
},
|
||||
"parameter": {
|
||||
"type": "component",
|
||||
"repeatable": false,
|
||||
"component": "configuration.parameter"
|
||||
},
|
||||
"privacy": {
|
||||
"type": "component",
|
||||
"repeatable": false,
|
||||
"component": "configuration.privacy"
|
||||
},
|
||||
"education": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,12 +33,10 @@ module.exports = (plugin) => {
|
||||
throw new Error("No access_token.");
|
||||
}
|
||||
|
||||
// Get the profile.
|
||||
const profile = await getProfile(provider, query);
|
||||
|
||||
const email = lod.toLower(profile.email);
|
||||
|
||||
// We need at least the mail.
|
||||
if (!email) {
|
||||
throw new Error("Email was not available.");
|
||||
}
|
||||
@@ -70,15 +68,13 @@ module.exports = (plugin) => {
|
||||
throw new Error("Email is already taken.");
|
||||
}
|
||||
|
||||
// Retrieve default role.
|
||||
const defaultRole = await strapi.db
|
||||
.query("plugin::users-permissions.role")
|
||||
.findOne({ where: { type: advancedSettings.default_role } });
|
||||
|
||||
// Create the new user.
|
||||
const newUser = {
|
||||
...profile,
|
||||
email, // overwrite with lowercased email
|
||||
email,
|
||||
provider,
|
||||
role: defaultRole.id,
|
||||
confirmed: true,
|
||||
@@ -93,6 +89,243 @@ module.exports = (plugin) => {
|
||||
};
|
||||
};
|
||||
|
||||
const originalMe = plugin.controllers.user.me;
|
||||
|
||||
plugin.controllers.user.me = async (ctx) => {
|
||||
const fullUser = await strapi.db
|
||||
.query("plugin::users-permissions.user")
|
||||
.findOne({
|
||||
where: { id: ctx.state.user.id },
|
||||
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;
|
||||
|
||||
const [
|
||||
contactsCount,
|
||||
groupsCount,
|
||||
postsCount,
|
||||
eventsCount,
|
||||
followersCount,
|
||||
followingCount,
|
||||
] = await Promise.all([
|
||||
strapi.db.query("api::contact.contact").count({
|
||||
where: {
|
||||
$or: [{ owner: userId }, { user: userId }],
|
||||
},
|
||||
}),
|
||||
strapi.db.query("api::group-membership.group-membership").count({
|
||||
where: {
|
||||
user: userId,
|
||||
role: { $in: ["owner", "member", "admin"] },
|
||||
},
|
||||
}),
|
||||
strapi.db
|
||||
.query("api::post-ownership.post-ownership")
|
||||
.count({ where: { author: userId } }),
|
||||
strapi.db
|
||||
.query("api::event-relationship.event-relationship")
|
||||
.count({ where: { author: userId } }),
|
||||
strapi.db.query("api::contact.contact").count({
|
||||
where: {
|
||||
user: userId,
|
||||
state: "follow",
|
||||
},
|
||||
}),
|
||||
strapi.db.query("api::contact.contact").count({
|
||||
where: {
|
||||
owner: userId,
|
||||
state: "follow",
|
||||
},
|
||||
}),
|
||||
]);
|
||||
const result = {
|
||||
...JSON.parse(JSON.stringify(fullUser)),
|
||||
stats: {
|
||||
contacts: contactsCount,
|
||||
groups: groupsCount,
|
||||
posts: postsCount,
|
||||
events: eventsCount,
|
||||
followers: followersCount,
|
||||
following: followingCount,
|
||||
},
|
||||
};
|
||||
|
||||
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]) {
|
||||
@@ -122,7 +355,6 @@ module.exports = (plugin) => {
|
||||
plugin.controllers.user.updateMe = async (ctx) => {
|
||||
const user = ctx.state.user;
|
||||
|
||||
// User has to be logged in to update themselves
|
||||
if (!user) {
|
||||
return ctx.unauthorized();
|
||||
}
|
||||
@@ -139,9 +371,31 @@ module.exports = (plugin) => {
|
||||
"voice",
|
||||
"job",
|
||||
"dob",
|
||||
"phone",
|
||||
"bio",
|
||||
"experience",
|
||||
"tags",
|
||||
"languages",
|
||||
"parameter",
|
||||
"privacy",
|
||||
]);
|
||||
|
||||
// Make sure there is no duplicate user with the same username
|
||||
/*
|
||||
if (data.tags) {
|
||||
newData.tags = data.tags.map((tag) => ({
|
||||
__component: "social.tags",
|
||||
text: tag.text,
|
||||
}));
|
||||
}
|
||||
|
||||
if (data.languages) {
|
||||
newData.languages = data.languages.map((lang) => ({
|
||||
__component: "user.language",
|
||||
language: lang.language,
|
||||
level: lang.level,
|
||||
}));
|
||||
}*/
|
||||
|
||||
if (newData.username) {
|
||||
const userWithSameUsername = await strapi
|
||||
.query("plugin::users-permissions.user")
|
||||
@@ -152,7 +406,6 @@ module.exports = (plugin) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure there is no duplicate user with the same email
|
||||
if (newData.email) {
|
||||
const userWithSameEmail = await strapi
|
||||
.query("plugin::users-permissions.user")
|
||||
@@ -167,12 +420,26 @@ module.exports = (plugin) => {
|
||||
ctx.request.body = newData;
|
||||
ctx.params = { id: user.id };
|
||||
|
||||
const avatarId = await uploadImage(ctx, "avatar", newData.username);
|
||||
if (avatarId != 0) ctx.request.body.avatar = avatarId;
|
||||
const backgroundId = await uploadImage(ctx, "background", newData.username);
|
||||
if (backgroundId != 0) ctx.request.body.background = backgroundId;
|
||||
const keysExcludingParameterAndPrivacy = Object.keys(newData).filter(
|
||||
(key) => key !== "parameter" && key !== "privacy"
|
||||
);
|
||||
|
||||
return plugin.controllers.user.update(ctx);
|
||||
if (keysExcludingParameterAndPrivacy.length === 0) {
|
||||
await strapi.entityService
|
||||
.update("plugin::users-permissions.user", user.id, {
|
||||
data: newData,
|
||||
})
|
||||
.then((res) => {
|
||||
ctx.response.status = 200;
|
||||
ctx.response.body = res;
|
||||
return ctx;
|
||||
});
|
||||
} else {
|
||||
const avatarId = await uploadImage(ctx, "avatar", newData.username);
|
||||
if (avatarId != 0) ctx.request.body.avatar = avatarId;
|
||||
|
||||
return plugin.controllers.user.update(ctx);
|
||||
}
|
||||
};
|
||||
|
||||
plugin.routes["content-api"].routes.push({
|
||||
|
||||
55
types/generated/components.d.ts
vendored
55
types/generated/components.d.ts
vendored
@@ -19,6 +19,39 @@ export interface AddressFullAddress extends Struct.ComponentSchema {
|
||||
};
|
||||
}
|
||||
|
||||
export interface ConfigurationParameter extends Struct.ComponentSchema {
|
||||
collectionName: 'components_configuration_parameters';
|
||||
info: {
|
||||
displayName: 'parameter';
|
||||
icon: 'cog';
|
||||
};
|
||||
attributes: {
|
||||
emailNotification: Schema.Attribute.Boolean &
|
||||
Schema.Attribute.DefaultTo<false>;
|
||||
pushNotification: Schema.Attribute.Boolean &
|
||||
Schema.Attribute.DefaultTo<false>;
|
||||
sendNewsgroup: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ConfigurationPrivacy extends Struct.ComponentSchema {
|
||||
collectionName: 'components_configuration_privacies';
|
||||
info: {
|
||||
description: '';
|
||||
displayName: 'privacy';
|
||||
icon: 'key';
|
||||
};
|
||||
attributes: {
|
||||
allowInvite: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<true>;
|
||||
allowMessage: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<true>;
|
||||
allowTag: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<true>;
|
||||
profileVisibility: Schema.Attribute.Enumeration<
|
||||
['public', 'contacts', 'private']
|
||||
>;
|
||||
showOnline: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<true>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface GroupActivity extends Struct.ComponentSchema {
|
||||
collectionName: 'components_group_activities';
|
||||
info: {
|
||||
@@ -26,8 +59,14 @@ export interface GroupActivity extends Struct.ComponentSchema {
|
||||
displayName: 'Activity';
|
||||
};
|
||||
attributes: {
|
||||
activityAvatar: Schema.Attribute.Media<
|
||||
'images' | 'files' | 'videos' | 'audios'
|
||||
>;
|
||||
activityDate: Schema.Attribute.DateTime;
|
||||
activityMessage: Schema.Attribute.String;
|
||||
activityType: Schema.Attribute.Enumeration<
|
||||
['user', 'group', 'choral', 'message', 'post', 'contact']
|
||||
>;
|
||||
activityUser: Schema.Attribute.String;
|
||||
};
|
||||
}
|
||||
@@ -43,6 +82,19 @@ export interface SocialTags extends Struct.ComponentSchema {
|
||||
};
|
||||
}
|
||||
|
||||
export interface UserLanguage extends Struct.ComponentSchema {
|
||||
collectionName: 'components_user_languages';
|
||||
info: {
|
||||
description: '';
|
||||
displayName: 'language';
|
||||
icon: 'feather';
|
||||
};
|
||||
attributes: {
|
||||
language: Schema.Attribute.String;
|
||||
level: Schema.Attribute.Integer;
|
||||
};
|
||||
}
|
||||
|
||||
export interface UserPermissions extends Struct.ComponentSchema {
|
||||
collectionName: 'components_user_permissions';
|
||||
info: {
|
||||
@@ -63,8 +115,11 @@ declare module '@strapi/strapi' {
|
||||
export module Public {
|
||||
export interface ComponentSchemas {
|
||||
'address.full-address': AddressFullAddress;
|
||||
'configuration.parameter': ConfigurationParameter;
|
||||
'configuration.privacy': ConfigurationPrivacy;
|
||||
'group.activity': GroupActivity;
|
||||
'social.tags': SocialTags;
|
||||
'user.language': UserLanguage;
|
||||
'user.permissions': UserPermissions;
|
||||
}
|
||||
}
|
||||
|
||||
133
types/generated/contentTypes.d.ts
vendored
133
types/generated/contentTypes.d.ts
vendored
@@ -584,6 +584,122 @@ export interface ApiChannelChannel extends Struct.CollectionTypeSchema {
|
||||
};
|
||||
}
|
||||
|
||||
export interface ApiChatConversationMemberChatConversationMember
|
||||
extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'chat_conversation_members';
|
||||
info: {
|
||||
displayName: 'ChatConversationMember';
|
||||
pluralName: 'chat-conversation-members';
|
||||
singularName: 'chat-conversation-member';
|
||||
};
|
||||
options: {
|
||||
draftAndPublish: false;
|
||||
};
|
||||
attributes: {
|
||||
conversation: Schema.Attribute.Relation<
|
||||
'oneToOne',
|
||||
'api::chat-conversation.chat-conversation'
|
||||
>;
|
||||
createdAt: Schema.Attribute.DateTime;
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||
Schema.Attribute.Private;
|
||||
joinedAt: Schema.Attribute.DateTime;
|
||||
lastReadAt: Schema.Attribute.DateTime;
|
||||
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
||||
localizations: Schema.Attribute.Relation<
|
||||
'oneToMany',
|
||||
'api::chat-conversation-member.chat-conversation-member'
|
||||
> &
|
||||
Schema.Attribute.Private;
|
||||
publishedAt: Schema.Attribute.DateTime;
|
||||
role: Schema.Attribute.Enumeration<['member', 'admin', 'owner']>;
|
||||
updatedAt: Schema.Attribute.DateTime;
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||
Schema.Attribute.Private;
|
||||
user: Schema.Attribute.Relation<
|
||||
'oneToOne',
|
||||
'plugin::users-permissions.user'
|
||||
>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ApiChatConversationChatConversation
|
||||
extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'chat_conversations';
|
||||
info: {
|
||||
description: '';
|
||||
displayName: 'ChatConversation';
|
||||
pluralName: 'chat-conversations';
|
||||
singularName: 'chat-conversation';
|
||||
};
|
||||
options: {
|
||||
draftAndPublish: false;
|
||||
};
|
||||
attributes: {
|
||||
createdAt: Schema.Attribute.DateTime;
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||
Schema.Attribute.Private;
|
||||
creator: Schema.Attribute.Relation<
|
||||
'oneToOne',
|
||||
'plugin::users-permissions.user'
|
||||
>;
|
||||
isGroup: Schema.Attribute.Boolean;
|
||||
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
||||
localizations: Schema.Attribute.Relation<
|
||||
'oneToMany',
|
||||
'api::chat-conversation.chat-conversation'
|
||||
> &
|
||||
Schema.Attribute.Private;
|
||||
messages: Schema.Attribute.Relation<
|
||||
'oneToMany',
|
||||
'api::chat-message.chat-message'
|
||||
>;
|
||||
publishedAt: Schema.Attribute.DateTime;
|
||||
title: Schema.Attribute.String;
|
||||
updatedAt: Schema.Attribute.DateTime;
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||
Schema.Attribute.Private;
|
||||
users: Schema.Attribute.Relation<
|
||||
'oneToMany',
|
||||
'plugin::users-permissions.user'
|
||||
>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ApiChatMessageChatMessage extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'chat_messages';
|
||||
info: {
|
||||
displayName: 'ChatMessage';
|
||||
pluralName: 'chat-messages';
|
||||
singularName: 'chat-message';
|
||||
};
|
||||
options: {
|
||||
draftAndPublish: false;
|
||||
};
|
||||
attributes: {
|
||||
content: Schema.Attribute.String & Schema.Attribute.Required;
|
||||
createdAt: Schema.Attribute.DateTime;
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||
Schema.Attribute.Private;
|
||||
deletedAt: Schema.Attribute.DateTime;
|
||||
isEdited: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>;
|
||||
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
||||
localizations: Schema.Attribute.Relation<
|
||||
'oneToMany',
|
||||
'api::chat-message.chat-message'
|
||||
> &
|
||||
Schema.Attribute.Private;
|
||||
publishedAt: Schema.Attribute.DateTime;
|
||||
sender: Schema.Attribute.Relation<
|
||||
'oneToOne',
|
||||
'plugin::users-permissions.user'
|
||||
>;
|
||||
updatedAt: Schema.Attribute.DateTime;
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||
Schema.Attribute.Private;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ApiChoralMembershipChoralMembership
|
||||
extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'choral_memberships';
|
||||
@@ -1047,7 +1163,7 @@ export interface ApiGroupMembershipGroupMembership
|
||||
Schema.Attribute.Private;
|
||||
publishedAt: Schema.Attribute.DateTime;
|
||||
role: Schema.Attribute.Enumeration<
|
||||
['member', 'admin', 'owner', 'follow', 'pending']
|
||||
['member', 'admin', 'owner', 'follow', 'pending', 'invited', 'rejected']
|
||||
>;
|
||||
updatedAt: Schema.Attribute.DateTime;
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||
@@ -1828,6 +1944,7 @@ export interface PluginUsersPermissionsUser
|
||||
draftAndPublish: false;
|
||||
};
|
||||
attributes: {
|
||||
activities: Schema.Attribute.Component<'group.activity', true>;
|
||||
address: Schema.Attribute.Text;
|
||||
announcements: Schema.Attribute.Relation<
|
||||
'oneToMany',
|
||||
@@ -1837,6 +1954,7 @@ export interface PluginUsersPermissionsUser
|
||||
background: Schema.Attribute.Media<
|
||||
'images' | 'files' | 'videos' | 'audios'
|
||||
>;
|
||||
bio: Schema.Attribute.Text;
|
||||
blocked: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>;
|
||||
board: Schema.Attribute.Relation<'oneToOne', 'api::board.board'>;
|
||||
choral_memberships: Schema.Attribute.Relation<
|
||||
@@ -1861,11 +1979,13 @@ 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<{
|
||||
minLength: 6;
|
||||
}>;
|
||||
experience: Schema.Attribute.Integer;
|
||||
friends: Schema.Attribute.Relation<
|
||||
'oneToMany',
|
||||
'plugin::users-permissions.user'
|
||||
@@ -1878,6 +1998,7 @@ export interface PluginUsersPermissionsUser
|
||||
job: Schema.Attribute.Enumeration<
|
||||
['choir_director', 'choir_addict', 'choir_master', 'choir_singer', 'none']
|
||||
>;
|
||||
languages: Schema.Attribute.JSON;
|
||||
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
||||
localizations: Schema.Attribute.Relation<
|
||||
'oneToMany',
|
||||
@@ -1885,10 +2006,7 @@ export interface PluginUsersPermissionsUser
|
||||
> &
|
||||
Schema.Attribute.Private;
|
||||
name: Schema.Attribute.String;
|
||||
nbFollowers: Schema.Attribute.Integer & Schema.Attribute.DefaultTo<0>;
|
||||
nbFollowing: Schema.Attribute.Integer & Schema.Attribute.DefaultTo<0>;
|
||||
nbPosts: Schema.Attribute.Integer & Schema.Attribute.DefaultTo<0>;
|
||||
nbSaved: Schema.Attribute.Integer & Schema.Attribute.DefaultTo<0>;
|
||||
parameter: Schema.Attribute.Component<'configuration.parameter', false>;
|
||||
password: Schema.Attribute.Password &
|
||||
Schema.Attribute.Private &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
@@ -1899,6 +2017,7 @@ export interface PluginUsersPermissionsUser
|
||||
'oneToMany',
|
||||
'api::post-ownership.post-ownership'
|
||||
>;
|
||||
privacy: Schema.Attribute.Component<'configuration.privacy', false>;
|
||||
provider: Schema.Attribute.String;
|
||||
publishedAt: Schema.Attribute.DateTime;
|
||||
related_contacts: Schema.Attribute.Relation<
|
||||
@@ -1912,6 +2031,7 @@ export interface PluginUsersPermissionsUser
|
||||
>;
|
||||
saved_posts: Schema.Attribute.Relation<'oneToMany', 'api::post.post'>;
|
||||
surname: Schema.Attribute.String;
|
||||
tags: Schema.Attribute.JSON;
|
||||
updatedAt: Schema.Attribute.DateTime;
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||
Schema.Attribute.Private;
|
||||
@@ -1943,6 +2063,9 @@ declare module '@strapi/strapi' {
|
||||
'api::board-list.board-list': ApiBoardListBoardList;
|
||||
'api::board.board': ApiBoardBoard;
|
||||
'api::channel.channel': ApiChannelChannel;
|
||||
'api::chat-conversation-member.chat-conversation-member': ApiChatConversationMemberChatConversationMember;
|
||||
'api::chat-conversation.chat-conversation': ApiChatConversationChatConversation;
|
||||
'api::chat-message.chat-message': ApiChatMessageChatMessage;
|
||||
'api::choral-membership.choral-membership': ApiChoralMembershipChoralMembership;
|
||||
'api::choral-permission.choral-permission': ApiChoralPermissionChoralPermission;
|
||||
'api::choral.choral': ApiChoralChoral;
|
||||
|
||||
Reference in New Issue
Block a user