0.12.4 : improve find user
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "harmony-back",
|
"name": "harmony-back",
|
||||||
"version": "0.12.3",
|
"version": "0.12.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "A Strapi application",
|
"description": "A Strapi application",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
"name": "Apache 2.0",
|
"name": "Apache 2.0",
|
||||||
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
|
"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": {
|
"x-strapi-config": {
|
||||||
"plugins": [
|
"plugins": [
|
||||||
@@ -17873,6 +17873,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -21530,6 +21533,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -25469,6 +25475,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -28967,6 +28976,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -32913,6 +32925,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -37110,6 +37125,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -41756,6 +41774,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -45692,6 +45713,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -49530,6 +49554,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -53355,6 +53382,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -57216,6 +57246,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -60969,6 +61002,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -64899,6 +64935,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -68902,6 +68941,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -72394,6 +72436,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -76815,6 +76860,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -80625,6 +80673,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -84756,6 +84807,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -88599,6 +88653,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -92546,6 +92603,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -96394,6 +96454,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -99747,6 +99810,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -104309,6 +104375,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -108200,6 +108269,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@@ -112051,6 +112123,9 @@
|
|||||||
"privacy": {
|
"privacy": {
|
||||||
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
"$ref": "#/components/schemas/ConfigurationPrivacyComponent"
|
||||||
},
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
|
|||||||
@@ -235,6 +235,9 @@
|
|||||||
"type": "component",
|
"type": "component",
|
||||||
"repeatable": false,
|
"repeatable": false,
|
||||||
"component": "configuration.privacy"
|
"component": "configuration.privacy"
|
||||||
|
},
|
||||||
|
"education": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,28 @@ module.exports = (plugin) => {
|
|||||||
populate: true,
|
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 user = ctx.state.user;
|
||||||
|
|
||||||
const userId = user.id;
|
const userId = user.id;
|
||||||
@@ -156,6 +178,154 @@ module.exports = (plugin) => {
|
|||||||
return result;
|
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 uploadImage = async (ctx, label: string, username: string) => {
|
||||||
const key = `${label}Image`;
|
const key = `${label}Image`;
|
||||||
if (ctx.request.files[key]) {
|
if (ctx.request.files[key]) {
|
||||||
|
|||||||
1
types/generated/contentTypes.d.ts
vendored
1
types/generated/contentTypes.d.ts
vendored
@@ -1863,6 +1863,7 @@ export interface PluginUsersPermissionsUser
|
|||||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
Schema.Attribute.Private;
|
Schema.Attribute.Private;
|
||||||
dob: Schema.Attribute.Date;
|
dob: Schema.Attribute.Date;
|
||||||
|
education: Schema.Attribute.String;
|
||||||
email: Schema.Attribute.Email &
|
email: Schema.Attribute.Email &
|
||||||
Schema.Attribute.Required &
|
Schema.Attribute.Required &
|
||||||
Schema.Attribute.SetMinMaxLength<{
|
Schema.Attribute.SetMinMaxLength<{
|
||||||
|
|||||||
Reference in New Issue
Block a user