From 460560bb89c7003a53bb95dbd9708acade0b9f2f Mon Sep 17 00:00:00 2001 From: julien vdb Date: Tue, 2 Dec 2025 23:06:50 +0100 Subject: [PATCH] 0.12.12 : add mail templates as single type --- package.json | 2 +- src/api/mails/content-types/mails/schema.json | 30 + src/api/mails/controllers/mails.ts | 7 + src/api/mails/routes/mails.ts | 7 + src/api/mails/services/mails.ts | 7 + src/components/mail/mail.json | 17 + .../1.0.0/full_documentation.json | 789 +++++++++++++++++- .../users-permissions/strapi-server.ts | 25 +- types/generated/components.d.ts | 14 + types/generated/contentTypes.d.ts | 36 + 10 files changed, 925 insertions(+), 9 deletions(-) create mode 100644 src/api/mails/content-types/mails/schema.json create mode 100644 src/api/mails/controllers/mails.ts create mode 100644 src/api/mails/routes/mails.ts create mode 100644 src/api/mails/services/mails.ts create mode 100644 src/components/mail/mail.json diff --git a/package.json b/package.json index 6b36d99..89610e2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "harmony-back", - "version": "0.12.11", + "version": "0.12.12", "private": true, "description": "A Strapi application", "scripts": { diff --git a/src/api/mails/content-types/mails/schema.json b/src/api/mails/content-types/mails/schema.json new file mode 100644 index 0000000..f1f0064 --- /dev/null +++ b/src/api/mails/content-types/mails/schema.json @@ -0,0 +1,30 @@ +{ + "kind": "singleType", + "collectionName": "mailss", + "info": { + "singularName": "mails", + "pluralName": "mailss", + "displayName": "Mails", + "description": "" + }, + "options": { + "draftAndPublish": false + }, + "pluginOptions": { + "i18n": { + "localized": true + } + }, + "attributes": { + "onCreateUser": { + "type": "component", + "repeatable": false, + "pluginOptions": { + "i18n": { + "localized": true + } + }, + "component": "mail.mail" + } + } +} diff --git a/src/api/mails/controllers/mails.ts b/src/api/mails/controllers/mails.ts new file mode 100644 index 0000000..fb99ab8 --- /dev/null +++ b/src/api/mails/controllers/mails.ts @@ -0,0 +1,7 @@ +/** + * mails controller + */ + +import { factories } from '@strapi/strapi' + +export default factories.createCoreController('api::mails.mails'); diff --git a/src/api/mails/routes/mails.ts b/src/api/mails/routes/mails.ts new file mode 100644 index 0000000..ea2bc67 --- /dev/null +++ b/src/api/mails/routes/mails.ts @@ -0,0 +1,7 @@ +/** + * mails router + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreRouter('api::mails.mails'); diff --git a/src/api/mails/services/mails.ts b/src/api/mails/services/mails.ts new file mode 100644 index 0000000..28e24be --- /dev/null +++ b/src/api/mails/services/mails.ts @@ -0,0 +1,7 @@ +/** + * mails service + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreService('api::mails.mails'); diff --git a/src/components/mail/mail.json b/src/components/mail/mail.json new file mode 100644 index 0000000..dcb0e88 --- /dev/null +++ b/src/components/mail/mail.json @@ -0,0 +1,17 @@ +{ + "collectionName": "components_mail_mail", + "info": { + "displayName": "mail", + "icon": "paperPlane", + "description": "" + }, + "options": {}, + "attributes": { + "subject": { + "type": "string" + }, + "message": { + "type": "text" + } + } +} diff --git a/src/extensions/documentation/documentation/1.0.0/full_documentation.json b/src/extensions/documentation/documentation/1.0.0/full_documentation.json index 62a3535..f53fc54 100644 --- a/src/extensions/documentation/documentation/1.0.0/full_documentation.json +++ b/src/extensions/documentation/documentation/1.0.0/full_documentation.json @@ -14,7 +14,7 @@ "name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html" }, - "x-generation-date": "2025-11-30T20:43:11.125Z" + "x-generation-date": "2025-12-02T22:06:43.585Z" }, "x-strapi-config": { "plugins": [ @@ -11170,6 +11170,329 @@ "operationId": "delete/invites/{id}" } }, + "/mails": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MailsResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Mails" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/mails" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MailsResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Mails" + ], + "parameters": [], + "operationId": "put/mails", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MailsRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Mails" + ], + "parameters": [], + "operationId": "delete/mails" + } + }, "/messages": { "get": { "responses": { @@ -102436,6 +102759,470 @@ } } }, + "MailsRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "properties": { + "onCreateUser": { + "$ref": "#/components/schemas/MailMailComponent" + }, + "locale": { + "type": "string" + }, + "localizations": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + } + } + } + } + }, + "MailsListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Mails" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "Mails": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + }, + "onCreateUser": { + "$ref": "#/components/schemas/MailMailComponent" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + }, + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + }, + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, + "permissions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + }, + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + }, + "locale": { + "type": "string" + }, + "localizations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + }, + "locale": { + "type": "string" + }, + "localizations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + }, + "locale": { + "type": "string" + }, + "localizations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + }, + "locale": { + "type": "string" + }, + "localizations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + }, + "onCreateUser": { + "$ref": "#/components/schemas/MailMailComponent" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + }, + "locale": { + "type": "string" + }, + "localizations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "MailsResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/Mails" + }, + "meta": { + "type": "object" + } + } + }, + "MailMailComponent": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "subject": { + "type": "string" + }, + "message": { + "type": "string" + } + } + }, "MessageRequest": { "type": "object", "required": [ diff --git a/src/extensions/users-permissions/strapi-server.ts b/src/extensions/users-permissions/strapi-server.ts index 8de7c59..d67e43a 100644 --- a/src/extensions/users-permissions/strapi-server.ts +++ b/src/extensions/users-permissions/strapi-server.ts @@ -46,6 +46,13 @@ module.exports = (plugin) => { const sendConfirmationEmail = async (user) => { // Génération du token de confirmation + const templates = await strapi + .documents("api::mails.mails") + .findFirst({ populate: "*" }); + //const onCreateUser = templates.onCreateUser; + + const onCreateUser = templates?.onCreateUser; + const confirmationToken = cryptoLib.randomBytes(20).toString("hex"); await edit(user.id, { confirmationToken }); @@ -54,7 +61,8 @@ module.exports = (plugin) => { // Lecture du template HTML depuis le fichier const htmlPath = path.join(process.cwd(), "public", "confirmation.html"); - let html = await fs.readFile(htmlPath, "utf-8"); + //let html = await fs.readFile(htmlPath, "utf-8"); + let html = onCreateUser?.message; // Remplacement des variables html = html @@ -63,12 +71,15 @@ module.exports = (plugin) => { .replace(/{{YEAR}}/g, new Date().getFullYear().toString()); // Envoi de l'e-mail - await strapi.plugin("email").service("email").send({ - to: user.email, - subject: "Confirme ton adresse e-mail", - html, - from: "ChoralSync ", - }); + await strapi + .plugin("email") + .service("email") + .send({ + to: user.email, + subject: onCreateUser?.subject ?? "Confirme ton adresse e-mail", + html, + from: "ChoralSync ", + }); return { ok: true }; }; diff --git a/types/generated/components.d.ts b/types/generated/components.d.ts index 4baf781..ed3c2f1 100644 --- a/types/generated/components.d.ts +++ b/types/generated/components.d.ts @@ -71,6 +71,19 @@ export interface GroupActivity extends Struct.ComponentSchema { }; } +export interface MailMail extends Struct.ComponentSchema { + collectionName: 'components_mail_mail'; + info: { + description: ''; + displayName: 'mail'; + icon: 'paperPlane'; + }; + attributes: { + message: Schema.Attribute.Text; + subject: Schema.Attribute.String; + }; +} + export interface SocialTags extends Struct.ComponentSchema { collectionName: 'components_social_tags'; info: { @@ -118,6 +131,7 @@ declare module '@strapi/strapi' { 'configuration.parameter': ConfigurationParameter; 'configuration.privacy': ConfigurationPrivacy; 'group.activity': GroupActivity; + 'mail.mail': MailMail; 'social.tags': SocialTags; 'user.language': UserLanguage; 'user.permissions': UserPermissions; diff --git a/types/generated/contentTypes.d.ts b/types/generated/contentTypes.d.ts index 3981740..ecdf3b3 100644 --- a/types/generated/contentTypes.d.ts +++ b/types/generated/contentTypes.d.ts @@ -1252,6 +1252,41 @@ export interface ApiInviteInvite extends Struct.CollectionTypeSchema { }; } +export interface ApiMailsMails extends Struct.SingleTypeSchema { + collectionName: 'mailss'; + info: { + description: ''; + displayName: 'Mails'; + pluralName: 'mailss'; + singularName: 'mails'; + }; + options: { + draftAndPublish: false; + }; + pluginOptions: { + i18n: { + localized: true; + }; + }; + attributes: { + createdAt: Schema.Attribute.DateTime; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + locale: Schema.Attribute.String; + localizations: Schema.Attribute.Relation<'oneToMany', 'api::mails.mails'>; + onCreateUser: Schema.Attribute.Component<'mail.mail', false> & + Schema.Attribute.SetPluginOptions<{ + i18n: { + localized: true; + }; + }>; + publishedAt: Schema.Attribute.DateTime; + updatedAt: Schema.Attribute.DateTime; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + }; +} + export interface ApiMessageMessage extends Struct.CollectionTypeSchema { collectionName: 'messages'; info: { @@ -2079,6 +2114,7 @@ declare module '@strapi/strapi' { 'api::group-membership.group-membership': ApiGroupMembershipGroupMembership; 'api::group.group': ApiGroupGroup; 'api::invite.invite': ApiInviteInvite; + 'api::mails.mails': ApiMailsMails; 'api::message.message': ApiMessageMessage; 'api::notification.notification': ApiNotificationNotification; 'api::permissions-template.permissions-template': ApiPermissionsTemplatePermissionsTemplate;