New upload way
Build release Docker image / Build Docker Images (push) Failing after 8m10s

This commit is contained in:
2026-05-04 18:46:41 +02:00
parent 6034c4f07b
commit 574d81ac54
5 changed files with 940 additions and 30 deletions
+8 -6
View File
@@ -23,16 +23,18 @@ export default () => ({
config: { config: {
provider: "aws-s3", provider: "aws-s3",
providerOptions: { providerOptions: {
baseUrl: "https://container.harmonylab.ovh/harmony", baseUrl: "https://container.choralsync.com",
credentials: { credentials: {
accessKeyId: "admin", accessKeyId: "a6f474b04f010543022788efc626cbfe",
secretAccessKey: "Apslxnap12bn23", secretAccessKey:
"eeeb631194378edee5145b3ef6314630b152fa186b3dab2fefdf8b48952cde21",
}, },
endpoint: "https://container.harmonylab.ovh", endpoint:
"https://4c59d3c67191bdd08e311a5a49c3ac98.r2.cloudflarestorage.com",
forcePathStyle: true, forcePathStyle: true,
region: "eu-west-3", region: "weur",
params: { params: {
Bucket: "harmony", Bucket: "choralsync",
}, },
}, },
}, },
File diff suppressed because it is too large Load Diff
+43
View File
@@ -0,0 +1,43 @@
module.exports = (plugin) => {
// 1. LE SECRET : On ajoute le champ 'path' au schéma officiel de Strapi.
// Strapi va ainsi créer la colonne en BDD et arrêter de supprimer notre variable.
plugin.contentTypes.file.schema.attributes.path = {
type: "string",
configurable: false,
};
const originalServiceFactory = plugin.services.upload;
plugin.services.upload = ({ strapi }) => {
const service = originalServiceFactory({ strapi });
return {
...service,
// 2. Surcharge de l'Uploader
async upload(fileData, usage) {
const ctx = strapi.requestContext.get();
// On récupère le custom path envoyé par ton client Next.js
const customPath = ctx?.request?.body?.path;
if (customPath) {
// Pour que le provider S3 l'utilise tout de suite (R2)
fileData.path = customPath;
// Pour que Strapi l'enregistre dans notre nouvelle colonne BDD
if (!fileData.fileInfo) fileData.fileInfo = {};
fileData.fileInfo.path = customPath;
}
// Le service original va maintenant sauvegarder le path en BDD !
return service.upload(fileData, usage);
},
// Note : Plus besoin de surcharger `remove` (l'équivalent de delete) !
// Comme la colonne 'path' est maintenant en BDD, le service original
// récupère l'info et la passe au provider S3 qui supprime le bon dossier.
};
};
return plugin;
};
@@ -26,7 +26,7 @@ module.exports = (plugin) => {
if (attributes[key] && attributes[key].type === "password") { if (attributes[key] && attributes[key].type === "password") {
// Check if a custom encryption.rounds has been set on the password attribute // Check if a custom encryption.rounds has been set on the password attribute
const rounds = toNumber( const rounds = toNumber(
getOr(10, "encryption.rounds", attributes[key]) getOr(10, "encryption.rounds", attributes[key]),
); );
values[key] = await bcrypt.hash(values[key], rounds); values[key] = await bcrypt.hash(values[key], rounds);
} }
@@ -186,14 +186,14 @@ module.exports = (plugin) => {
if (fullUser.contacts && Array.isArray(fullUser.contacts)) { if (fullUser.contacts && Array.isArray(fullUser.contacts)) {
fullUser.contacts = fullUser.contacts.filter( fullUser.contacts = fullUser.contacts.filter(
(contact) => contact.state === "accepted" (contact) => contact.state === "accepted",
); );
} }
if (fullUser.post_ownerships && Array.isArray(fullUser.post_ownerships)) { if (fullUser.post_ownerships && Array.isArray(fullUser.post_ownerships)) {
fullUser.post_ownerships = fullUser.post_ownerships.filter( fullUser.post_ownerships = fullUser.post_ownerships.filter(
(ownership) => (ownership) =>
ownership.contextType === "user" && ownership.relation === "owner" ownership.contextType === "user" && ownership.relation === "owner",
); );
} }
@@ -202,7 +202,7 @@ module.exports = (plugin) => {
Array.isArray(fullUser.group_memberships) Array.isArray(fullUser.group_memberships)
) { ) {
fullUser.group_memberships = fullUser.group_memberships.filter( fullUser.group_memberships = fullUser.group_memberships.filter(
(membership) => ["member", "admin", "owner"].includes(membership.role) (membership) => ["member", "admin", "owner"].includes(membership.role),
); );
} }
@@ -324,27 +324,27 @@ module.exports = (plugin) => {
}, },
activities: true, activities: true,
}, },
} },
); );
// Fusionne les données originales (permissions/serialization) avec les relations // Fusionne les données originales (permissions/serialization) avec les relations
user = { ...user, ...populatedUser }; user = { ...user, ...populatedUser };
if (user.contacts && Array.isArray(user.contacts)) { if (user.contacts && Array.isArray(user.contacts)) {
user.contacts = user.contacts.filter( user.contacts = user.contacts.filter(
(contact) => contact.state === "accepted" (contact) => contact.state === "accepted",
); );
} }
if (user.post_ownerships && Array.isArray(user.post_ownerships)) { if (user.post_ownerships && Array.isArray(user.post_ownerships)) {
user.post_ownerships = user.post_ownerships.filter( user.post_ownerships = user.post_ownerships.filter(
(ownership) => (ownership) =>
ownership.contextType === "user" && ownership.relation === "owner" ownership.contextType === "user" && ownership.relation === "owner",
); );
} }
if (user.group_memberships && Array.isArray(user.group_memberships)) { if (user.group_memberships && Array.isArray(user.group_memberships)) {
user.group_memberships = user.group_memberships.filter((membership) => user.group_memberships = user.group_memberships.filter((membership) =>
["member", "admin", "owner"].includes(membership.role) ["member", "admin", "owner"].includes(membership.role),
); );
} }
@@ -411,7 +411,12 @@ module.exports = (plugin) => {
return ctx; return ctx;
}; };
const uploadImage = async (ctx, label: string, username: string) => { const uploadImage = async (
ctx,
label: string,
username: string,
userId: number,
) => {
const key = `${label}Image`; const key = `${label}Image`;
if (ctx.request.files[key]) { if (ctx.request.files[key]) {
const files = Array.isArray(ctx.request.files[key]) const files = Array.isArray(ctx.request.files[key])
@@ -424,6 +429,7 @@ module.exports = (plugin) => {
alternativeText: username || "", alternativeText: username || "",
name: `${username}_avatar${extension}`, name: `${username}_avatar${extension}`,
}, },
path: `user/${userId}`,
}; };
const asset = await strapi.services["plugin::upload.upload"].upload({ const asset = await strapi.services["plugin::upload.upload"].upload({
data: payload, data: payload,
@@ -444,7 +450,14 @@ module.exports = (plugin) => {
return ctx.unauthorized(); return ctx.unauthorized();
} }
const data = JSON.parse(ctx.request.body.data); let data;
if (ctx.request.body.data && typeof ctx.request.body.data === 'string') {
data = JSON.parse(ctx.request.body.data);
} else if (ctx.request.body.data && typeof ctx.request.body.data === 'object') {
data = ctx.request.body.data;
} else {
data = ctx.request.body;
}
const newData = lod.pick(data, [ const newData = lod.pick(data, [
"email", "email",
@@ -463,6 +476,7 @@ module.exports = (plugin) => {
"languages", "languages",
"parameter", "parameter",
"privacy", "privacy",
"avatar",
]); ]);
/* /*
@@ -506,7 +520,7 @@ module.exports = (plugin) => {
ctx.params = { id: user.id }; ctx.params = { id: user.id };
const keysExcludingParameterAndPrivacy = Object.keys(newData).filter( const keysExcludingParameterAndPrivacy = Object.keys(newData).filter(
(key) => key !== "parameter" && key !== "privacy" (key) => key !== "parameter" && key !== "privacy",
); );
if (keysExcludingParameterAndPrivacy.length === 0) { if (keysExcludingParameterAndPrivacy.length === 0) {
@@ -520,9 +534,6 @@ module.exports = (plugin) => {
return ctx; return ctx;
}); });
} else { } else {
const avatarId = await uploadImage(ctx, "avatar", newData.username);
if (avatarId != 0) ctx.request.body.avatar = avatarId;
return plugin.controllers.user.update(ctx); return plugin.controllers.user.update(ctx);
} }
}; };
@@ -533,14 +544,12 @@ module.exports = (plugin) => {
await sendConfirmationEmail(result); await sendConfirmationEmail(result);
await strapi await strapi.service("api::notification.notification")?.addActivity({
.service("api::notification.notification") userId: result.id,
?.addActivity({ activityMessage: `Bienvenue ${result.username}, Ton compte est maintenant activé.`,
userId: result.id, activityUser: result.username,
activityMessage: `Bienvenue ${result.username}, Ton compte est maintenant activé.`, activityType: "user",
activityUser: result.username, });
activityType: "user",
});
// Appel du service de notification // Appel du service de notification
await strapi await strapi
@@ -555,7 +564,7 @@ module.exports = (plugin) => {
}); });
strapi.log.info( strapi.log.info(
`🔔 Notification envoyée pour l'utilisateur ${result.id}` `🔔 Notification envoyée pour l'utilisateur ${result.id}`,
); );
}, },
}; };
+1
View File
@@ -1971,6 +1971,7 @@ export interface PluginUploadFile extends Struct.CollectionTypeSchema {
Schema.Attribute.Private; Schema.Attribute.Private;
mime: Schema.Attribute.String & Schema.Attribute.Required; mime: Schema.Attribute.String & Schema.Attribute.Required;
name: Schema.Attribute.String & Schema.Attribute.Required; name: Schema.Attribute.String & Schema.Attribute.Required;
path: Schema.Attribute.String;
previewUrl: Schema.Attribute.String; previewUrl: Schema.Attribute.String;
provider: Schema.Attribute.String & Schema.Attribute.Required; provider: Schema.Attribute.String & Schema.Attribute.Required;
provider_metadata: Schema.Attribute.JSON; provider_metadata: Schema.Attribute.JSON;